home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / cocktail / doc.lha / doc.doc / estra.doc < prev    next >
Text File  |  1992-09-25  |  168KB  |  5,627 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.                       Spezifikation und Implementierung
  11.                    der Transformation attributierter Baeume
  12.  
  13.  
  14.  
  15.  
  16.  
  17.                                Bertram Vielsack
  18.  
  19.  
  20.  
  21.  
  22.                                  Diplomarbeit
  23.  
  24.  
  25.                Universitaet Karlsruhe Fakultaet fuer Informatik
  26.  
  27.  
  28.                                   Juni 1989
  29.  
  30.  
  31.  
  32.  
  33.  
  34.                                   Betreuer:
  35.  
  36.                               Prof. Dr. G. Goos
  37.                            Prof. Dr. S. Jaehnichen
  38.                                 Dr. J. Grosch
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78.  
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105.  
  106.  
  107.  
  108.     Hiermit erklaere ich, dasz ich  die  vorliegende  Arbeit  selbstaendig
  109.     erstellt  habe  und  keine  anderen  als  die  angegebenen Quellen und
  110.     Hilfsmittel verwendet habe.
  111.  
  112.  
  113.  
  114.     Karlsruhe, im Juni 1989
  115.  
  116.  
  117.  
  118.                                                          (Bertram    Viel-
  119.     sack)
  120.  
  121.  
  122.  
  123.  
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.  
  134.  
  135.                                       4
  136.  
  137.  
  138. 1.  Einleitung
  139.  
  140. Bei der Erstellung von Uebersetzern spielen Zwischensprachen, die durch attri-
  141. butierte Baeume dargestellt werden, eine wichtige Rolle.  Die Zwischensprachen
  142. gliedern den komplexen Uebersetzungsvorgang in  mehrere  Transformationen  und
  143. damit  den Entwurf und die Entwicklung eines Uebersetzers in mehrere unabhaen-
  144. gige Teilaufgaben.
  145.  
  146. Wesentliche Aufgaben beim Bau eines Uebersetzers bestehen also darin, attribu-
  147. tierte  Baeume  zu  transformieren.  Das  Ergebnis  einer  Transformation kann
  148. wiederum ein  attributierter  Baum  sein.  Andere  Strukturen  (Graph,  Liste,
  149. sequentielle Ausgabe etc.) sind ebenso moeglich. Der einheitlichen Darstellung
  150. der Eingabe steht also eine Vielfalt an  Moeglichkeiten  zur  Darstellung  der
  151. Ausgabe gegenueber.
  152.  
  153. Ein  Ziel  der  vorliegenden  Arbeit  ist  die  Entwicklung  einer  Spezifika-
  154. tionssprache (ESTRAL[1]) zur Beschreibung von Transformationen. Diese  Sprache
  155. musz  einerseits  an  die  einheitliche  Struktur  der Eingabe angepaszt sein.
  156. Andererseits muessen universelle Mittel zur Beschreibung  der  Ausgabe  bereit
  157. gestellt werden.
  158.  
  159. Zur automatischen Umsetzung einer Spezifikation in eine  Implementierung  wird
  160. ein Generator (ESTRA[2]) entwickelt.
  161.  
  162. Spezifikationssprache und Generator zusammen ermoeglichen es,  bei  der  Real-
  163. isierung  von  Transformationen  attributierter Baeume von der Implementierung
  164. auf eine problemorientierte Spezifikation ueberzugehen.
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184.  
  185.  
  186. ____________________
  187.    [1]ESTRAL - Efficient Structure tree TRAnsformation Language
  188.    [2]ESTRA - Efficient Structure tree TRAnsformation
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.                                       5
  201.  
  202.  
  203. 2.  Moeglichkeiten zur Beschreibung von Transformationen
  204.  
  205. Eine Transformation im Sinne dieser Arbeit ist jede Abbildung  eines  attribu-
  206. tierten  Baumes.  Ob es sich beim Ergebnis einer solchen Abbildung wiederum um
  207. einen attributierten Baum handelt  oder  nicht  spielt  hierbei  keine  Rolle.
  208. Entscheidend ist einzig die Struktur der Eingabe.
  209.  
  210. Es werden drei unterschiedliche Moeglichkeiten zur Beschreibung von  Transfor-
  211. mationen vorgestellt.
  212.  
  213. 2.1.  Attributierte Grammatiken
  214.  
  215. Attributierte Grammatiken (AGs) [Knu68] werden  im  Uebersetzerbau  vorwiegend
  216. eingesetzt, um die Semantische Analyse zu beschreiben. Sie werden aber auch zu
  217. Beschreibung der Codeerzeugung und  -optimierung  benutzt.  AGs  koennen  auch
  218. benutzt werden, um Transformationen zu beschreiben.
  219.  
  220. Normalerweise wird dabei so vorgegangen, dasz das Ergebnis der  Transformation
  221. durch  den Wert eines Attributs an der Wurzel des Baumes dargestellt wird. Die
  222. Konsequenz  dieser  Vorgehensweise  ist,  dasz  das  komplette  Ergebnis   der
  223. Transformation  als  Wert  gespeichert  werden musz. Falls eine Ausgabe dieses
  224. Wertes erfolgen soll, musz dies auszerhalb des AG-Kalkuels beschrieben werden.
  225. Die Verwendung von Seiteneffekten zum sequentiellen Aufbau der Ausgabe ist mit
  226. diesem Ansatz nicht ohne weiteres moeglich, da die  Reihenfolge,  in  der  die
  227. einzelnen Attribute berechnet werden, nicht unmittelbar gesteuert werden kann.
  228.  
  229. Falls der Wunsch besteht, Seiteneffekte einzusetzen (z.B.  zur  Dateiausgabe),
  230. musz  die  gewuenschte  Auswertungsreihenfolge  durch Verwendung zusaetzlicher
  231. Attribute mit entsprechenden  Abhaengigkeiten  erzwungen  werden.  Diese  kom-
  232. plizierte  und  aufwendige  Art der Steuerung der Reihenfolge, die zudem recht
  233. unnatuerlich ist, koennte vermieden werden, wenn der sequentielle Ablauf durch
  234. imperative Programmierung unmittelbar beschrieben werden koennte.
  235.  
  236. Transformationen realisieren in der Regel Abbildungen, die  mehrere  Loesungen
  237. zulassen  und  einen  sequentiellen  Aufbau  einer  solchen Loesung nahelegen.
  238. Transformationen sind also von Natur aus mehrdeutig und  sequentiell.  Es  ist
  239. deshalb sinnvoll, zur Beschreibung einer Transformation eine mehrdeutige Spez-
  240. ifikation zu verwenden. Die Attributberechnung musz allerdings auf alle Faelle
  241. eindeutig  sein.   Mehrdeutigkeit in der Logik der Transformation musz deshalb
  242. in der AG zur Beschreibung der Transformation durch zusaetzliche Attribute und
  243. Berechnungen eindeutig gemacht werden.
  244.  
  245. Auf Grund der mehrdeutigen und sequentiellen Natur von Transformationen bieten
  246. AGs in ihrer Reinform keine ausreichenden Mittel, um Transformationen sinnvoll
  247. zu beschreiben.
  248.  
  249. 2.2.  Modifikation der Eingabe
  250.  
  251. Eine weitere Moeglichkeit, Transformationen durchzufuehren besteht darin,  die
  252. Ausgabe  durch  Modifikation der Eingabe zu erzeugen, wie es beispielsweise in
  253. [MWW84] beschrieben wird.  Der  Eingabebaum  wird  hier  in  einem  iterativen
  254. Prozesz   so  lange  umgebaut,  bis  das  Ergebnis  der  gewuenschten  Ausgabe
  255. entspricht.  Die Transformation kann beschrieben werden, indem  die  einzelnen
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.  
  266. 6                      2. Moeglichkeiten zur Beschreibung von Transformationen
  267.  
  268.  
  269. Schritte  diese  Prozeszes  durch Vorschriften festgelegt werden.  Die Eleganz
  270. dieser  Methode  besteht  darin,  dasz  eine  Transformation  durch   einzelne
  271. aufeinander  aufbauende  Schritte  einfach  und anschaulich beschrieben werden
  272. kann.
  273.  
  274. Die Reihenfolge und der Ort, auf den die einzelnen Vorschriften angewandt wer-
  275. den,  kann  die  Anwendung  weiterer  Vorschriften  und  letztlich das gesamte
  276. Ergebnis entscheidend beeinflussen.   Zur  Beschreibung  einer  Transformation
  277. musz  deshalb  neben  den  Vorschriften  eine Strategie festgelegt werden, die
  278. Reihenfolge und Ort der Regelanwendungen bestimmt.
  279.  
  280. Es ist moeglich und i.a. sogar erwuenscht, dasz durch eine  Modifikation  eine
  281. weitere  Modifikation erst moeglich wird. Das birgt jedoch die Gefahr in sich,
  282. dasz der iterative Prozesz nie endet, da immer weitere Modifikationen moeglich
  283. werden.  Neben der Frage nach der Terminierung ergeben sich aus diesem Umstand
  284. Probleme  bei  der  Abschaetzung  des  Aufwands,  der  zur  Durchfuehrung  der
  285. Transformation erforderlich ist.
  286.  
  287. Bei einer Modifikation kann nicht ausgeschlossen werden, dasz  die  Werte  der
  288. Attribute des Baumes verloren gehen oder zumindest inkonsistent werden.  Falls
  289. die einzelnen Vorschriften an Bedingungen ueber die Attribute geknuepft werden
  290. sollen,  ist  es  deshalb  notwendig, unmittelbar nach jeder Modifikation eine
  291. Reattributierung durchzufuehren.  Wenn man auf  eine  Reattributierung  verzi-
  292. chten  will,  verbleibt  die  Moeglichkeit,  die Modifikation der Eingabe ein-
  293. zusetzen, um nicht attributierte Baeume zu transformieren.
  294.  
  295. 2.3.  Funktionale Abbildung
  296.  
  297. Das Wesen einer funktionalen Abbildung  eines  attributierten  Baumes  besteht
  298. darin,  dasz der Ausgabewert neu berechnet wird, der alte Eingabebaum wird nur
  299. gelesen und bleibt somit unveraendert. Das Problem der  Reattributierung,  wie
  300. es bei der Modifikation der Eingabe besteht, kann folglich nicht entstehen.
  301.  
  302. Durch eine imperative Beschreibung der Abbildung ist es unmittelbar  moeglich,
  303. die  Reihenfolge der Abarbeitung zu steuern, so dasz eine sequentielle Ausgabe
  304. durch den Einsatz von Seiteneffekten ebenso moeglich ist wie der Aufbau  eines
  305. neuen Baumes.
  306.  
  307. Eine mehrdeutige Beschreibung von Transformationen ist durch den  Einsatz  von
  308. Mustern und Kosten auf einfache und elegante Weise moeglich.
  309.  
  310. Das sequentielle und mehrdeutige Wesen von Transformationen  kann  mit  dieser
  311. Methode  unmittelbar  beschrieben  werden. Probleme, die durch den Einsatz von
  312. AGs oder die Modifikation der Eingabe entstehen, werden somit vermieden.
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319.  
  320.  
  321.  
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.                                       7
  332.  
  333.  
  334. 3.  Anforderungen an eine funktionale Beschreibung
  335.  
  336. Im folgenden wird an Beispielen gezeigt, welche Anforderungen eine funktionale
  337. Beschreibung  von  Transformationen  erfuellen  musz,  und mit welchen Mitteln
  338. diese erfuellt werden koennen.
  339.  
  340. Die einfuehrenden Beispiele aus dem  Bereich  der  Codeerzeugung  wurden  aus-
  341. gewaehlt,  da  sie  sich  eignen  viele Probleme, die bei der Beschreibung von
  342. Transformationen entstehen, darzustellen. Gleichwohl sind dies nicht die  typ-
  343. ischen  Anwendungsbeispiele,  da fuer die Beschreibung der Codeerzeugung spez-
  344. ielle Sprachen und Werkzeuge [Emm88] existieren.
  345.  
  346. Die in den Beispielen verwendete Notation  gibt  einen  Vorgeschmack  auf  die
  347. Spezifikationssprache ESTRAL, die in Kapitel 5 ausfuehrlich beschrieben wird.
  348.  
  349. 3.1.  Abbildung der einzelnen Knoten
  350.  
  351. Eine einfache Methode, Strukturbaeume zu transformieren, besteht  darin,  alle
  352. Knoten  eines  Baumes  zu  besuchen  und dabei das Ergebnis der Transformation
  353. sukzessive durch Abbildung der einzelnen Knoten zu erzeugen. Wuerde  man  eine
  354. feste Reihenfolge (z.B. Postfix) zum Besuch der einzelnen Knoten festlegen, so
  355. wuerde es genuegen, die Abbildung fuer jeden Knoten  festzulegen.  Diese  ein-
  356. fache  Methode  waere  bereits  ausreichend, um Code zur Berechnung von arith-
  357. metischen Ausdruecken auf einer Kellermaschine zu erzeugen (Abb. 3.1).
  358.  
  359.  
  360.     ______________________________________________________________________
  361.  
  362.     TRANSFORMATION T
  363.       A     {  Emit (Push A);       }
  364.       B     {  Emit (Push B);       }
  365.       C     {  Emit (Push C);       }
  366.       '*'   {  Emit (Multiply);     }
  367.       '+'   {  Emit (Add);          }
  368.  
  369.     ______________________________________________________________________
  370.  
  371.     Abb. 3.1: Transformation eines Strukturbaumes
  372.  
  373.  
  374. Doch ist diese Methode nur begrenzt einsetzbar.  Betrachten  wir  hierzu  fol-
  375. gendes Beispiel (Abb. 3.2).
  376.  
  377.  
  378.     ______________________________________________________________________
  379.  
  380.     ______________________________________________________________________
  381.  
  382.     Abb. 3.2: Strukturbaum einer Zuweisung
  383.  
  384.  
  385. Hier waere es offensichtlich falsch, fuer den ersten Operanden  der  Zuweisung
  386. ein  'Push  A'  zu generieren. Hingegen ist dies fuer den ersten Operanden der
  387. Addition weiterhin erforderlich. Auszerdem zeigt das Beispiel, dasz eine feste
  388. Ablaufstrategie  (wie  Postfix)  zum  Besuch  der einzelnen Knoten nicht immer
  389. brauchbar ist, denn bevor die Zuweisung erfolgen kann  (Abb.  3.2),  musz  die
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.  
  398.  
  399.  
  400. 8                            3. Anforderungen an eine funktionale Beschreibung
  401.  
  402.  
  403. Summe berechnet werden.  D.h. die Addition mit ihren Operanden A und B ist vor
  404. dem linken Operand der Zuweisung zu besuchen.
  405.  
  406. 3.2.  Steuerung der Reihenfolge
  407.  
  408. Derartige Probleme koennen geloest werden,  wenn  man  die  Transformation  in
  409. Funktionen  gliedert  und  sowohl  die  Reihenfolge  als auch die Art der dur-
  410. chzufuehrenden Funktionen vom Kontext abhaengig macht.
  411.  
  412.  
  413.     ______________________________________________________________________
  414.  
  415.     TRANSFORMATION CODE
  416.     FUNCTION PUSH
  417.       ':='  {   F1 (':='.ro); F2 (':='.lo);                 }
  418.       A     {   Emit (Push A);                              }
  419.       B     {   Emit (Push B);                              }
  420.       '+'   {   F1 ('+'.lo); F1 ('+'.ro); Emit (Add);               }
  421.     FUNCTION STORE
  422.       A     {   Emit (Store A);                             }
  423.       B     {   Emit (Store B);                             }
  424.  
  425.     ______________________________________________________________________
  426.  
  427.     Abb. 3.3: Gliederung einer Transformation in mehrere Funktionen
  428.  
  429.  
  430. In den Vorschriften (Abb. 3.3) erfolgt ein expliziter Aufruf von zum Teil ver-
  431. schiedenen Funktionen fuer die einzelnen Operanden (.lo bezeichnet hierbei den
  432. linken,  .ro  den  rechten  Operanden  des  angegebenen  Knotens).  Die  Abar-
  433. beitungsreihenfolge ist nun explizit spezifiziert.
  434.  
  435. 3.3.  Zugriff auf die Attribute
  436.  
  437. Die Vorschriften zur Abbildung der Knoten A und B in Abb.  3.3  sind  offensi-
  438. chtlich  aehnlich. Dies liegt daran, dasz es sich jeweils um einen Knoten han-
  439. delt, der eine Variable darstellt. In solchen Faellen sollte es moeglich sein,
  440. die  Abbildung  durch  eine  einzige  Vorschrift  zu  beschreiben.  Um  das zu
  441. erreichen, fassen wir die Namen der Variablen als Attribute auf.  Ein  nunmehr
  442. attributierter Strukturbaum erhaelt damit etwa folgende Gestalt (Abb. 3.4).
  443.  
  444.  
  445.     ______________________________________________________________________
  446.  
  447.     ______________________________________________________________________
  448.  
  449.     Abb. 3.4: Attributierter Strukturbaum einer Zuweisung
  450.  
  451.  
  452. An Stelle der Knoten A und B erscheinen nur noch Knoten vom Typ V  (Variable),
  453. die  ein  Attribut N (Name der Variablen) besitzen, das hier die Werte A und B
  454. annimmt. Die Beschreibung der Transformation nimmt dann folgende Form an (Abb.
  455. 3.5).
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.  
  464.  
  465.  
  466.  
  467. 3.3. Zugriff auf die Attribute                                               9
  468.  
  469.  
  470.  
  471.     ______________________________________________________________________
  472.  
  473.     TRANSFORMATION CODE
  474.     FUNCTION PUSH
  475.       ':='  {   F1 (':='.ro); F2 (':='.lo);                 }
  476.       V     {   Emit (Push V.N);                            }
  477.       '+'   {   F1 ('+'.lo); F1 ('+'.ro); Emit (Add);               }
  478.     FUNCTION STORE
  479.       V     {   Emit (Store V.N);                           }
  480.     ______________________________________________________________________
  481.  
  482.     Abb. 3.5: Beschreibung der Transformation eines attributierten Strukturbaumes
  483.  
  484.  
  485.  
  486. 3.4.  Berechnung eines synthetisierten Attributs
  487.  
  488. Bei der bisher betrachteten Kellermaschine werden  Ergebnisse  eines  Teilaus-
  489. drucks  auf dem Keller abgelegt. Hat man es dagegen mit einer Registermaschine
  490. zu tun, wird man Zwischenergebnisse in einem Register  ablegen.  Um  nun  Code
  491. fuer  eine  Operation  zu  erzeugen, ist es erforderlich, zu wissen in welchen
  492. Registern die Zwischenergebnisse stehen.
  493.  
  494. Diese Information kann zur Verfuegung gestellt werden, wenn  gleichzeitig  mit
  495. der  Transformation eine S-Attributierung (Attributierung, bei der nur synthe-
  496. tisierte Attribute berechnet werden) durchgefuehrt wird. Da die Attribute  bei
  497. der Transformation unmittelbar verarbeitet werden, ist es nicht notwendig, sie
  498. explizit im Baum zu speichern, es genuegt, wenn die Attribute unmittelbar nach
  499. der  Transformation eines Teilbaums zur Verfuegung stehen. Dies wird erreicht,
  500. indem die Attribute als Ergebnisse der einzelnen Funktionen  dargestellt  wer-
  501. den.
  502.  
  503. In Abb. 3.6 wird dieser Mechanismus benutzt um festzuhalten, in welchem Regis-
  504. ter  das Zwischenergebnis steht. Die Funktion Reg, die die Transformation dur-
  505. chfuehrt, liefert dieses Register als Ergebnis.
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.  
  520.  
  521.  
  522.  
  523.  
  524.  
  525.  
  526.  
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533. 10                           3. Anforderungen an eine funktionale Beschreibung
  534.  
  535.  
  536.  
  537.     ______________________________________________________________________
  538.  
  539.     TRANSFORMATION T
  540.     FUNCTION Reg: register
  541.       '+'   {
  542.             i := Reg ('+'.lo);
  543.             j := Reg ('+'.ro);
  544.             Emit (ADD Rj, Ri);
  545.             FreeReg (j);            (* Register j ist nun wieder frei *)
  546.             RETURN i;
  547.             }
  548.       '*'   {
  549.             i := Reg ('*'.lo);
  550.             j := Reg ('*'.ro);
  551.             Emit (MULS Rj, Ri);
  552.             FreeReg (j);            (* Register j ist nun wieder frei *)
  553.             RETURN i;
  554.             }
  555.       V     {
  556.             i := GetReg ();         (* Beschaffe Register fuer Zwischenergebnis *)
  557.             Emit (MOVE V.N@, Ri);
  558.             RETURN i;
  559.             }
  560.  
  561.     ______________________________________________________________________
  562.  
  563.     Abb. 3.6: S-Attributierung
  564.  
  565.  
  566. Die Registervergabe erfolgt 'on the fly'. Um das Beispiel einfach  zu  halten,
  567. wurde  davon  ausgegangen,  dasz  immer genuegend Register vorhanden sind, was
  568. z.B. dann der Fall ist, wenn bei der Erzeugung von Zwischencode Pseudoregister
  569. an Stelle der realen Register verwendet werden.
  570.  
  571. Das Beispiel in Abb. 3.6 zeigt, dasz es nun  prinzipiell  moeglich  ist,  eine
  572. Transformation  zu  beschreiben,  die Code fuer eine Registermaschine liefert.
  573. Allerdings ist der generierte Code schlecht im Vergleich zu der  in  Abb.  3.7
  574. angegebenen Transformation.
  575.  
  576.  
  577.     ______________________________________________________________________
  578.  
  579.     ______________________________________________________________________
  580.  
  581.     Abb. 3.7: optimierte Transformation eines arithmetischen Ausdrucks
  582.  
  583.  
  584.  
  585. 3.5.  Muster
  586.  
  587. Offensichtlich ist es nicht erforderlich, die zweiten Operanden  der  Addition
  588. und  Multiplikation in ein Hilfsregister zu laden, wenn es sich dabei wie hier
  589. um eine (direkt zugreifbare) Variable handelt. Da wir aber bislang  immer  nur
  590.  
  591.  
  592.  
  593.  
  594.  
  595.  
  596.  
  597.  
  598.  
  599.  
  600. 3.5. Muster                                                                 11
  601.  
  602.  
  603. einzelne  Knoten  abgebildet haben, konnte bei der Transformation der Addition
  604. (bzw. Multiplikation) nicht erkannt werden, ob es sich beim rechten  Operanden
  605. um  eine  Variable  handelt.   Im  folgenden  werden wir deshalb an Stelle von
  606. einzelnen Knoten (kleine) Ausschnitte  moeglicher  Strukturbaeume,  sogenannte
  607. Muster, verwenden, um eine Transformation festzulegen.
  608.  
  609. Diese Muster muessen nun auf den Teil des Strukturbaums passen,  der  mit  dem
  610. aktuellen  (d.h.  dem  zu transformierenden) Knoten beginnt. Die Muster werden
  611. durch ihre geklammerte Prefixform dargestellt. Um  Operanden  zu  beschreiben,
  612. die  nicht eindeutig festgelegt sind, koennen Nichtterminale verwendet werden.
  613. So wird z.B. in Abb. 3.8 das Nichtterminal expr verwendet, wenn beliebige Aus-
  614. druecke erlaubt sind. Um in den Anweisungen leichter auf den Baum zugreifen zu
  615. koennen, koennen die Namen  der  Knoten  und  Nichtterminale,  die  im  Muster
  616. stehen, verwendet werden. Falls es hierbei zu Mehrdeutigkeit kommt, kann diese
  617. durch freigewaehlte Bezeichner, die im Muster mit angegeben werden, aufgeloest
  618. werden (siehe e1 und e2 in Abb. 3.8).
  619.  
  620. Mit Hilfe von Mustern sollte es nun  moeglich  sein,  eine  Transformation  zu
  621. beschreiben, die in der Lage ist, den optimalen Code von Abb. 3.7 zu erzeugen.
  622. Dazu erweitern wir die Beschreibung von Abb. 3.6 um zwei Vorschriften, die die
  623. Spezialfaelle  behandeln,  dasz  es sich beim rechten Operanden einer Addition
  624. bzw. Multiplikation um eine (direkt zugreifbare) Variable handelt.
  625.  
  626. 3.6.  Mehrdeutigkeit und Kosten
  627.  
  628. Offensichtlich musz die dadurch entstandene Beschreibung mehrdeutig  sein,  da
  629. ja  die alte Moeglichkeit der nicht optimalen Codeerzeugung weiterhin besteht.
  630. Damit die optimale Loesung ausgewaehlt werden kann,  werden  Kosten  fuer  die
  631. Vorschriften eingefuehrt.  Mit Hilfe dieser Kosten lassen sich dann die Kosten
  632. der  Transformation  als  Summe  der  Kosten  aller  angewandten  Vorschriften
  633. berechnen.  Im  Falle einer Mehrdeutigkeit wird nun die optimale Loesung, d.h.
  634. die Loesung mit den geringsten Kosten ausgewaehlt.
  635.  
  636. Wenn die Laenge des erzeugten Codes zur  Festlegung  der  Kosten  herangezogen
  637. wird, ergibt sich fuer unser Beispiel die Beschreibung von Abb. 3.8.
  638.  
  639.  
  640.  
  641.  
  642.  
  643.  
  644.  
  645.  
  646.  
  647.  
  648.  
  649.  
  650.  
  651.  
  652.  
  653.  
  654.  
  655.  
  656.  
  657.  
  658.  
  659.  
  660.  
  661.  
  662.  
  663.  
  664.  
  665. 12                           3. Anforderungen an eine funktionale Beschreibung
  666.  
  667.  
  668.  
  669.     ______________________________________________________________________
  670.  
  671.     TRANSFORMATION T
  672.     FUNCTION Reg: Register
  673.       '+' (e1: expr, e2: expr)      COST 2
  674.                             {
  675.                             i := Reg (e1); j := Reg (e2);
  676.                             Emit (ADD Rj, Ri);
  677.                             FreeReg (j); RETURN i;
  678.                             }
  679.       '*' (e1: expr, e2: expr)      COST 2
  680.                             {
  681.                             i := Reg (e1); j := Reg (e2);
  682.                             Emit (MULS Rj, Ri);
  683.                             FreeReg (j); RETURN i;
  684.                             }
  685.       V ()                  COST 4
  686.                             {
  687.                             i := GetReg ();
  688.                             Emit (MOVE V.N@, Ri);
  689.                             RETURN i;
  690.                             }
  691.       '+' (expr, V ())              COST 4
  692.                             {       (* rechter Operand ist eine Variable *)
  693.                             i := Reg (expr);
  694.                             Emit (ADD V.N@, Ri)
  695.                             RETURN i;
  696.                             }
  697.       '*' (expr, V ())              COST 4
  698.                             {       (* rechter Operand ist eine Variable *)
  699.                             i := Reg (expr);
  700.                             Emit (MULS V.N@, Ri)
  701.                             RETURN i;
  702.                             }
  703.     ______________________________________________________________________
  704.  
  705.     Abb. 3.8: Mehrdeutigkeit und Kosten zur Optimierung einer Transformation
  706.  
  707.  
  708. Betrachten wir nochmals die Loesungen von  Abb.  3.6  und  3.7  und  berechnen
  709. jeweils  die  Kosten. Im ersten Fall ergibt sich eine Summe von 16, im zweiten
  710. (optimierten) Fall sind es nur 12. Die Einfuehrung  von  Kosten  liefert  also
  711. offensichtlich das gewuenschte Ergebnis.
  712.  
  713. 3.7.  Bedingungen
  714.  
  715. Attribute des Strukturbaumes wurden  bislang  nur  benutzt,  um  die  bei  der
  716. Codeerzeugung  notwendigen  konkreten  Werte (z.B. Adressen) zur Verfuegung zu
  717. stellen.  Es kann aber auch vorkommen, dasz eine Vorschrift nur dann verwendet
  718. werden darf, wenn Attributwerte eine spezielle Bedingung erfuellen.
  719.  
  720.  
  721.  
  722.  
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729. 3.7. Bedingungen                                                            13
  730.  
  731.  
  732.  
  733.     ______________________________________________________________________
  734.  
  735.     ______________________________________________________________________
  736.  
  737.     Abb. 3.9: Produkt einer Variablen mit einer Konstanten (Zweierpotenz)
  738.  
  739.  
  740. Um beispielsweise das Produkt einer Variablen und der Konstanten 4 (Abb.  3.9)
  741. zu  berechnen,  genuegt  es, den Wert der Variablen um zwei Binaerstellen nach
  742. links zu verschieben. Dieses Verfahren geht  aber  offensichtlich  nicht  fuer
  743. beliebige  Konstanten, sondern nur fuer solche, die eine Zweierpotenz darstel-
  744. len. Um dies durch eine Vorschrift beschreiben zu  koennen,  fuehren  wir  die
  745. Moeglichkeit ein, eine Vorschrift mit einer Bedingung (condition) zu verknuep-
  746. fen (Abb. 3.10).
  747.  
  748.  
  749.     ______________________________________________________________________
  750.  
  751.       '*' (expr, C ())              COST 2
  752.                             CONDITION { IsPowerOf2 (C.V) }
  753.                             {
  754.                             i := Reg (expr);
  755.                             d := Log2 (C.V);
  756.                             Emit (ASL #d, Ri)
  757.                             RETURN i;
  758.                             }
  759.     ______________________________________________________________________
  760.  
  761.     Abb. 3.10: Vorschrift mit einer Bedingung
  762.  
  763.  
  764. Durch die Kombination Mehrdeutigkeit, Bedingungen und Kosten ist es  auf  ein-
  765. fache  Weise  moeglich,  Transformatoren zu beschreiben, die in der Lage sind,
  766. eine optimierte Abbildung durchzufuehren.
  767.  
  768. 3.8.  Mehrfachtransformation
  769.  
  770. Eine weiteres Mittel bei der Beschreibung von  Transformationen,  das  in  den
  771. bisherigen  Beispielen noch nicht verwendet wurde, ist die Mehrfachtransforma-
  772. tion. Eine Mehrfachtransformation liegt dann vor, wenn ein  Teilbaum  mehrmals
  773. auf die selbe (Abb. 3.13) oder auf unterschiedliche Weise transformiert wird.
  774.  
  775.  
  776.  
  777.  
  778.  
  779.  
  780.  
  781.  
  782.  
  783.  
  784.  
  785.  
  786.  
  787.  
  788.  
  789.  
  790.  
  791.  
  792.  
  793.  
  794.  
  795.  
  796.  
  797. 14                           3. Anforderungen an eine funktionale Beschreibung
  798.  
  799.  
  800.  
  801.     ______________________________________________________________________
  802.  
  803.     TRANSFORMATION T
  804.     FUNCTION Copy: tree
  805.       WHILE (expr, stmt)    {
  806.                             e1 := Copy (expr);
  807.                             s  := Copy (stmt);
  808.                             e2 := Copy (expr);
  809.                             e3 := MakeNOT (e2);
  810.                             r  := MakeREPEAT (s, e3);
  811.                             RETURN MakeIF (e1, r);
  812.                             }
  813.  
  814.     ______________________________________________________________________
  815.  
  816.     Abb. 3.11: Transformation einer While-Schleife
  817.  
  818.  
  819. Eine While-Schleife kann  durch  eine  Repeat-Schleife  ersetzt  werden,  wenn
  820. letztere  in  eine  bedingte Anweisung (IF) eingeschlossen wird.  Der Ausdruck
  821. (expr) der Bedingung musz hierzu offensichtlich dupliziert werden.  Abb.  3.11
  822. zeigt, wie dies durch eine Mehrfachtransformation realisiert wird.
  823.  
  824. Eine andere Form der Mehrfachtransformation ist die  mehrfache  Transformation
  825. eines   Strukturbaumes   auf  unterschiedliche  Weise.  Bei  dieser  Form  der
  826. Mehrfachtransformation  werden  verschiedene  Funktionen  auf  einen  Teilbaum
  827. angewandt.
  828.  
  829. 3.9.  Synthetisierte und vererbte Attribute
  830.  
  831. Bei komplexen  Transformation  reicht  eine  S-Attributierung,  wie  sie  2.4.
  832. eingefuehrt, nicht aus.
  833.  
  834. Ein Beispiel fuer eine solche Transformation ist die Normierung des  Struktur-
  835. baumes  eines  regulaeren Ausdrucks. Ein regulaerer Ausdruck ist ein Ausdruck,
  836. der den folgenden Regeln gehorcht:
  837.  
  838. 1.   jeder Bezeichner (Identifier) ist ein regulaerer Ausdruck
  839.  
  840. 2.   wenn R1 und R2 regulaere Ausdruecke sind, dann sind auch:
  841.        R1 '|' R2     (Alternative)
  842.        R1 R2 (Sequenz)
  843.        (R1)
  844.        R1 '*'        (Wiederholung)
  845.      Regulaere Ausdruecke.
  846.  
  847. Da es sich bei der Sequenz (das selbe gilt fuer die Alternative) um eine asso-
  848. ziative  Operation  handelt,  gibt es unterschiedliche Moeglichkeiten zur Dar-
  849. stellung des selben regulaeren Ausdrucks in Form eines  Strukturbaumes.  Durch
  850. die  unnoetige  Verwendung  von  Klammern  oder die automatische Erzeugung von
  851. regulaeren Ausdruecken ist es unter Umstaenden unvermeidlich, dasz diese  ver-
  852. schiedenen Strukturbaeume tatsaechlich aufgebaut werden.
  853.  
  854.  
  855.  
  856.  
  857.  
  858.  
  859.  
  860.  
  861.  
  862.  
  863. 3.9. Synthetisierte und vererbte Attribute                                  15
  864.  
  865.  
  866.  
  867.     ______________________________________________________________________
  868.  
  869.     ______________________________________________________________________
  870.  
  871.     Abb. 3.12: verschiedene Darstellungen des selben regulaeren Ausdrucks
  872.  
  873.  
  874. Um solche Strukturbaeume (Abb. 3.12) zu normieren, d.h. fuer eine einheitliche
  875. Darstellung  der regulaeren Ausdruecke zu sorgen, geht man zweckmaeszigerweise
  876. wie folgt vor:
  877.  
  878. 1.   Nicht assoziative und unaere Operatoren werden eins zu eins abgebildet.
  879.  
  880. 2.   Beim Antreffen eines assoziativen Operators werden alle darunterliegenden
  881.      Knoten  mit  demselben  Operator  zusammengefaszt.  Die darunterliegenden
  882.      Teilbaeume werden der Reihe nach transformiert. Dabei wird ein normierter
  883.      (zur  Liste entarteter) Baum mit dem aktuellen Operator aufgebaut, dessen
  884.      Blaetter durch die Transformationsergebnisse der Teilbaeume gebildet wer-
  885.      den.
  886.  
  887. Um dies zu realisieren reicht eine S-Attributierung deshalb  nicht  aus,  weil
  888. die  Baeume zur Normierung nicht nur hochgereicht, d.h. synthetisiert, sondern
  889. auch nach unten gegeben d.h. vererbt werden muessen.
  890.  
  891. Um diese Vererbung beschreiben zu koennen, ordnen wir einer  Funktion  zusaet-
  892. zlich  zum Ergebnisattribut noch weitere vererbte und synthetisierte Attribute
  893. zu. Diese Attribute muessen beim Aufruf einer Funktion neben dem zu  transfor-
  894. mierenden  Strukturbaum,  der immer das erste Argument bildet, uebergeben wer-
  895. den.
  896.  
  897.  
  898.     ______________________________________________________________________
  899.  
  900.     TRANSFORMATION OrderTree
  901.  
  902.     FUNCTION Order: tTree
  903.       Alt (r1: RegExpr, r2: RegExpr){ RETURN OrderAlt (r2, Order (r1)); }
  904.       Seq (r1: RegExpr, r2: RegExpr){ RETURN OrderSeq (r2, Order (r1)); }
  905.       Star (RegExpr)            { RETURN MakeSTAR (Order (RegExpr)); }
  906.       Ident ()                  { RETURN MakeIdent (Ident.Name); }
  907.  
  908.     FUNCTION OrderSeq   List: tTree -> : tTree
  909.       Seq (r1: RegExpr, r2: RegExpr)COST 1{ RETURN OrderSeq (r2, OrderSeq (r1, List)); }
  910.       Ident ()          COST 1  { RETURN MakeSEQ (List, MakeIdent (Ident.Name)); }
  911.       RegExpr           COST 2  { RETURN MakeSEQ (List, Order (RegExpr)); }
  912.  
  913.     FUNCTION OrderAlt   List: tTree -> : tTree
  914.       Alt (r1: RegExpr, r2: RegExpr)COST 1{ RETURN OrderAlt (r2, OrderAlt (r1, List)); }
  915.       Ident ()          COST 1  { RETURN MakeALT (List, MakeIdent (Ident.Name)); }
  916.       RegExpr           COST 2  { RETURN MakeALT (List, Order (RegExpr)); }
  917.     ______________________________________________________________________
  918.  
  919.     Abb. 3.13: Normierung eines regulaeren Ausdruckes durch Transformation
  920.  
  921.  
  922.  
  923.  
  924.  
  925.  
  926.  
  927.  
  928.  
  929.  
  930.  
  931. 16                           3. Anforderungen an eine funktionale Beschreibung
  932.  
  933.  
  934. Die Funktion OrderSeq sammelt die gesamte Sequenz ein und baut mit  Hilfe  des
  935. vererbten  Attributs  List  (vererbte Attribute stehen links von Pfeil ('->'),
  936. synthetisierte rechts) und dem Ergebnisattribut sukzessive den normierten Baum
  937. fuer die Sequenz auf. Die allgemeine Vorschrift (die Vorschrift mit dem Muster
  938. 'RegExpr') wird aufgrund der Kosten nur fuer die  uebrigen  Operatoren  (nicht
  939. fuer  die Sequenz) gewaehlt. Sie stoeszt dann wiederum die Funktion Order fuer
  940. den aktuellen Knoten an. Die  Funktion  OrderAlt  arbeitet  entsprechend  fuer
  941. Alternativen.
  942.  
  943.  
  944.  
  945.  
  946.  
  947.  
  948.  
  949.  
  950.  
  951.  
  952.  
  953.  
  954.  
  955.  
  956.  
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963.  
  964.  
  965.  
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972.  
  973.  
  974.  
  975.  
  976.  
  977.  
  978.  
  979.  
  980.  
  981.  
  982.  
  983.  
  984.  
  985.  
  986.  
  987.  
  988.  
  989.  
  990.  
  991.  
  992.  
  993.  
  994.  
  995.  
  996.                                       17
  997.  
  998.  
  999. 4.  Begriffe
  1000.  
  1001. Bevor weiter auf die Spezifikation und  die  Implementierung  von  Transforma-
  1002. tionen eingegangen wird, muessen einige zentrale Begriffe geklaert werden.
  1003.  
  1004. 4.1.  Baumgrammatik
  1005.  
  1006. Eine  Baumgrammatik  ist  eine  spezielle  kontextfreie  Grammatik,  die  hier
  1007. eingesetzt   wird,   um  die  Struktur  der  zu  transformierenden  Baeume  zu
  1008. beschreiben.
  1009.  
  1010. Eine Baumgrammatik ist ein Viertupel G = (C, N, P, Z) mit
  1011.  
  1012. 1.   C = Menge der Klassen
  1013.  
  1014. 2.   N = Menge der Knoten
  1015.  
  1016. 3.   P = Menge der Produktionen  C x (C U N C*)
  1017.  
  1018. 4.   Z = Menge der Startsymbole  C
  1019.  
  1020. Die Klassen C einer Baumgrammatik entsprechen den Nichtterminalen, die  Knoten
  1021. den Terminalen einer gewoehnlichen kontextfreien Grammatik.
  1022.  
  1023. Bei den Produktionen P einer Baumgrammatik werden zwei Typen unterschieden:
  1024.  
  1025. 1.   Kettenproduktion:
  1026.      c<0> -> c<1> mit c<0>, c<1>  C
  1027.  
  1028. 2.   Knotenproduktion:
  1029.      c<0> -> n (c<1>, ..., c<m>) mit n  N, c<0>, c<1>, ..., c<m>  C
  1030.  
  1031. Die Kettenproduktion ersetzt eine Klasse c<0> durch  eine  Klasse  c<1>;  c<0>
  1032. heiszt Oberklasse von c<1>.
  1033.  
  1034. Bei der Knotenproduktion werden ein Knoten n aufgebaut, und die Klassen  c<1>,
  1035. ...,  c<m>  seiner Soehne festgelegt.  Da die rechte Seite einer Knotenproduk-
  1036. tion einen Knoten n beschreibt wird sie auch als Knotenbeschreibung (oder kurz
  1037. Beschreibung)  des  Knotens  n  bezeichnet.  Die Klammern in den Knotenproduk-
  1038. tionen haben keine Bedeutung, sie erhoehen jedoch die Lesbarkeit und ermoegli-
  1039. chen  auszerdem die Unterscheidung von Ketten- und Knotenproduktionen aufgrund
  1040. der Darstellung.
  1041.  
  1042. Damit eine Grammatik fuer unsere Zwecke brauchbar ist,  muessen  weitere  For-
  1043. derungen erfuellt werden:
  1044.  
  1045. 1.   Zyklenfreiheit:
  1046.      c<0> -> c<1> -> ...  -> c<m>
  1047.  
  1048.      c<0> / c<m>
  1049.      die Kettenproduktionen muessen azyklisch sein
  1050.  
  1051.  
  1052.  
  1053.  
  1054.  
  1055.  
  1056.  
  1057.  
  1058.  
  1059.  
  1060.  
  1061. 18                                                                 4. Begriffe
  1062.  
  1063.  
  1064. 2.   Eindeutigkeit der Oberklasse:
  1065.      c<1> -> c<0>, c<2> -> c<0>
  1066.  
  1067.      c<1> = c<2>
  1068.      jede Klasse besitzt hoechstens eine Oberklasse:
  1069.  
  1070. 3.   Feste Wertigkeit:
  1071.      c<0> -> n (c<1>, ..., c<m>), c<0> -> n (c<1>, ..., c<m'>)
  1072.  
  1073.      m = m'
  1074.      die Anzahl der Soehne ist fuer alle  Knotenbeschreibungen  eines  Knotens
  1075.      identisch
  1076.  
  1077. 4.   Eindeutigkeit der Knotenbeschreibung innerhalb einer Klasse:
  1078.      c<0> -> n (c<1>, ..., c<m>), c<0> -> n (c<1>, ..., c<m>)
  1079.  
  1080.      c<1> = c<1>, ..., c<m> = c<m>,
  1081.      ein Knoten darf in einer Klasse nur einmal beschrieben sein
  1082.  
  1083. 5.   Prinzip der Hauptbeschreibung:
  1084.       n  N:
  1085.       c<0> -> n (c<1>, ..., c<m>)  P:
  1086.      c<0> -> n (c<1>, ..., c<m>)  P
  1087.  
  1088.      c<0> -> ... -> c<0>, c<1> -> ... -> c<1>, ..., c<m> -> ... -> c<m>
  1089.      fuer jeden Knoten  existiert  eine  Beschreibung,  aus  der  alle  andern
  1090.      Beschreibungen des selben Knotens abgeleitet werden koennen.
  1091.  
  1092. 6.   Reduziertheit:
  1093.      Von der Baumgrammatik wird verlangt, dasz sie reduziert ist,  d.h.   alle
  1094.      Klassen  und Knoten muessen von den Startsymbolen aus erreichbar sein und
  1095.      alle Klassen muessen terminalisierbar sein.
  1096.  
  1097. Die Eigenschaften erleichtern zum einen die Darstellung und den Umgang mit der
  1098. Baumgrammatik,  andererseits  sind  sie notwendig damit die Baeume vernuenftig
  1099. implementiert werden koennen.
  1100.  
  1101.  
  1102.  
  1103.  
  1104.  
  1105.  
  1106.  
  1107.  
  1108.  
  1109.  
  1110.  
  1111.  
  1112.  
  1113.  
  1114.  
  1115.  
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121.  
  1122.  
  1123.  
  1124.  
  1125.  
  1126. 4.1. Baumgrammatik                                                          19
  1127.  
  1128.  
  1129.  
  1130.     ______________________________________________________________________
  1131.  
  1132.     G = (C, N, P, Z)
  1133.  
  1134.     C = {expr, const, index}
  1135.     N = {'+', Const, Ident}
  1136.     P = {   expr      ->const,
  1137.         expr    ->    index,
  1138.         expr    ->    '+'(expr, expr),
  1139.         const   ->    Const(),
  1140.         const   ->    '+'(const, const),
  1141.         index   ->    Ident() }
  1142.     Z = {expr}
  1143.     ______________________________________________________________________
  1144.  
  1145.     Abb. 4.1: Baumgrammatik fuer arithmetische Ausdruecke
  1146.  
  1147.  
  1148. Abb. 4.1 zeigt eine Baumgrammatik fuer  arithmetische  Ausdruecke,  die  diese
  1149. Forderungen erfuellt. Die Grammatik ist zyklenfrei (1).  Die Klassen const und
  1150. index besitzen beide die eindeutige Oberklasse expr (2). Beide  Beschreibungen
  1151. von  '+' haben die Wertigkeit zwei (3) und liegen in unterschiedlichen Klassen
  1152. (4). Die Produktion expr -> '+' (expr, expr) legt die Hauptbeschreibung  fest.
  1153. Die  zweite  Knotenproduktion  fuer '+' (const -> '+' (const, const)) kann aus
  1154. der ersteren abgeleitet werden (5). Die Grammatik ist reduziert (6).
  1155.  
  1156. 4.2.  Muster
  1157.  
  1158. Wenn man ausgehend von  einer  Klasse  endlich  viele  Produktionen  anwendet,
  1159. entsteht ein Ausdruck, den wir als Muster bezeichnen. Muster werden verwendet,
  1160. um die Menge aller aus ihnen ableitbaren Baeumen darzustellen.
  1161.  
  1162. Wenn ein Baum aus einem Muster abgeleitet werden kann, dann paszt  das  Muster
  1163. auf diesen Baum.
  1164.  
  1165. Bei der Darstellung von Mustern ist es zulaessig,  Klassen  wegzulassen,  wenn
  1166. diese  aufgrund der Hauptbeschreibung ohnehin festgelegt sind.  Diese Freiheit
  1167. hat zur Folge, dasz es verschiedene Muster gibt, die die selbe Menge von Baeu-
  1168. men darstellen.
  1169.  
  1170. Abb. 4.2 zeigt ein Beispiel. Die Doppelpunkte in den Mustern dienen als  Plat-
  1171. zhalter  fuer die weggelassenen Klassen. Der Doppelpunkt stellt das sogenannte
  1172. allgemeine Muster, das immer paszt, dar.
  1173.  
  1174.  
  1175.  
  1176.  
  1177.  
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192.  
  1193. 20                                                                 4. Begriffe
  1194.  
  1195.  
  1196.  
  1197.     ______________________________________________________________________
  1198.  
  1199.     '+' (:, :)    (normiert)
  1200.     '+' (expr, :)
  1201.     '+' (:, expr)
  1202.     '+' (expr, expr)
  1203.     ______________________________________________________________________
  1204.  
  1205.     Abb. 4.2: verschiedene Muster zur Darstellung der selben Mengen von Baeumen
  1206.  
  1207.  
  1208. Da in der Grammatik von Abb. 4.1 Ident der einzige Knoten  ist,  der  aus  der
  1209. Klasse  index  abgeleitet werden kann, stellen die beiden Muster von Abbildung
  1210. 4.3 ebenfalls die selbe Menge von Baeumen dar.
  1211.  
  1212.  
  1213.     ______________________________________________________________________
  1214.  
  1215.     index         (normiert)
  1216.     Ident         ()
  1217.     ______________________________________________________________________
  1218.  
  1219.     Abb. 4.3: verschiedene Muster zur Darstellung der selben Mengen von Baeumen
  1220.  
  1221.  
  1222.  
  1223. Der Grund fuer die Moeglichkeit, ein Menge von Baeumen durch verschiedene Mus-
  1224. ter  darzustellen,  ist also zum einen die Moeglichkeit, die Klasse des Sohnes
  1225. nicht zu spezifizieren, zum anderen die Eigenschaft, dasz ein Knoten  mitunter
  1226. bereits durch eine Klasse eindeutig festgelegt ist.
  1227.  
  1228. Um diese unterschiedliche Darstellungen zu vermeiden,  wird  der  Begriff  des
  1229. normierten  Musters eingefuehrt. Ein Muster heiszt normiert, wenn es durch die
  1230. zwei oben genannten Eigenschaften (Klasse der Soehne musz  nicht  spezifiziert
  1231. werden, Knoten ist durch Klasse festgelegt) nicht vereinfacht werden kann.
  1232.  
  1233. Eine dritte Moeglichkeit besteht,  wenn  die  Oberklasse  einer  Klasse  keine
  1234. eigenen Knotenbeschreibungen enthaelt und fuer keine weitere Klasse Oberklasse
  1235. ist. In diesem Fall kann aus der  Oberklasse  nichts  abgeleitet  werden,  was
  1236. nicht  auch  aus  der  Klasse selbst entstehen koennte. Somit sind diese beide
  1237. Klassen bei der Darstellung eines Musters vollkommen austauschbar.
  1238.  
  1239. In der Praxis wird diese Moeglichkeit in der Regel  nicht  auftreten,  da  man
  1240. normalerweise   versuchen  wird,  mit  einer  moeglichst  einfachen  Grammatik
  1241. auszukommen und deshalb das Auftreten aequivalenter Klassen vermieden wird.
  1242.  
  1243. 4.3.  Beziehungen zwischen Mustern
  1244.  
  1245. Um die Beziehungen zwischen zwei Mustern beschreiben zu  koennen,  werden  die
  1246. folgenden Begriffe und Notationen verwendet.
  1247.  
  1248. 1.   p<1> = p<2>
  1249.      Zwei Muster sind gleich, falls gilt, dasz entweder  beide  Muster  passen
  1250.      oder keines der Muster paszt.
  1251.  
  1252.  
  1253.  
  1254.  
  1255.  
  1256.  
  1257.  
  1258.  
  1259.  
  1260.  
  1261. 4.3. Beziehungen zwischen Mustern                                           21
  1262.  
  1263.  
  1264. 2.   p<1> < p<2>
  1265.      Ein Muster p<1> ist kleiner als p<2>, wenn das Passen von  p<1>  aus  dem
  1266.      Passen von p<2> folgt und die beiden Muster nicht gleich sind.
  1267.  
  1268. 3.   p<1> > p<2>
  1269.      Ein Muster p<1> ist groeszer als p<2>, wenn p<2> kleiner als p<1> ist.
  1270.  
  1271. 4.   p<1> || p<2>
  1272.      Ein Muster p<1> ist inkonsistent zu p<2>, wenn es keinen Baum  gibt,  auf
  1273.      den sowohl p<1> als auch p<2> paszt.
  1274.  
  1275. 5.   p<1> ~ p<2>
  1276.      Ein Muster p<1> ist unabhaengig von p<2>, wenn p<1> und p<2>  unabhaengig
  1277.      voneinander passen koennen.
  1278.  
  1279. Die Begriffe sind [HoO82] entnommen. Dort werden jedoch  keine  unterschiedli-
  1280. chen  Klassen  betrachtet,  wie es hier geschieht.  Statt dessen gibt es ledi-
  1281. glich ein Symbol, das fuer beliebige Baeume steht.
  1282.  
  1283. Die Einfuehrung von Klassen  hat  zur  Folge,  dasz  es  aufwendiger  wird  zu
  1284. berechnen, welche Beziehung zwischen zwei Mustern gilt.
  1285.  
  1286. Betrachten wir den Fall, dasz es sich bei den beiden Mustern  jeweils  nur  um
  1287. eine  Klasse handelt. Die Frage nach der Beziehung zwischen den beiden Mustern
  1288. ist dann gleichbedeutend zu entscheiden,  ob  die  Sprachen,  die  durch  zwei
  1289. unterschiedliche Baumgrammatiken definiert werden, identisch sind (gleich), ob
  1290. eine Sprache eine  Untermenge  der  anderen  ist  (kleiner/groeszer),  ob  der
  1291. Schnitt  der  beiden Sprachen leer ist (inkonsistent) oder ob es sich um Quer-
  1292. mengen handelt (unabhaengig).
  1293.  
  1294. In der Praxis ist es jedoch moeglich, mit einer Naeherungsloesung auszukommen.
  1295. Diese  Naeherungsloesung entsteht, indem in einzelnen Faellen in Kauf genommen
  1296. wird, dasz zwei Muster als unabhaengig  betrachtet  werden,  obwohl  eine  der
  1297. anderen  Beziehungen  gilt.  Dieser Fehler kann in Kauf genommen werden, da er
  1298. nur in pathologischen Faellen eintritt und keine Folgefehler verursacht.
  1299.  
  1300. Im Algorithmus zur Berechnung der Beziehung zwischen zwei (normierten) Mustern
  1301. (Abb. 4.5) werden folgende Hilfsfunktionen verwendet (Abb. 4.4).
  1302.  
  1303.  
  1304.     ______________________________________________________________________
  1305.  
  1306.     Ident (pat: tPattern): tIdent                            (* liefert den Bezeichner der Wurzel von pat*)
  1307.     Type  (id: tIdent): tType                                (* liefert den Typ (class oder node) von id*)
  1308.     Arity (node: tIdent): INTEGER                            (* liefert die Wertigkeit des Knotens*)
  1309.     Classes                 (pat: tPattern): tSet            (* liefert die Klassen zu denen pat gehoert*)
  1310.     Subclasses (class: tIdent): tSet                         (* liefert die Unterklassen von class*)
  1311.     ClassesOfNode (node: tIdent): tSet                       (* liefert alle Klassen in denen node beschrieben ist*)
  1312.     NodesOfClass (class: tIdent): tSet                       (* liefert alle Knoten die aus class hervorgehen koennen*)
  1313.     ______________________________________________________________________
  1314.  
  1315.     Abb. 4.4: Hilfsfunktionen zur Berechnung der Beziehung zwischen zwei Mustern
  1316.  
  1317.  
  1318.  
  1319.  
  1320.  
  1321.  
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.  
  1328. 22                                                                 4. Begriffe
  1329.  
  1330.  
  1331.  
  1332.     ______________________________________________________________________
  1333.  
  1334.     Relation (pat1, pat2: tPattern): tRelation;
  1335.     if (pat1 = NoPat) & (pat2 = NoPat) then return equal(* pat1 = pat2*)
  1336.     if (pat1 = NoPat) then return less (* pat1 < pat2  *)
  1337.     if (pat2 = NoPat) then return greater              (* pat1 > pat2*)
  1338.     id1 := Ident (pat1)
  1339.     type1 := Type (id1)
  1340.     id2 := Ident (pat2)
  1341.     type2 := Type (id2)
  1342.     if (type1 = class) & (type2 = class) then          (* A *)
  1343.       if (id1 = id2) then return equal (* pat1 = pat2  *)
  1344.       elsif (id1  Classes (pat2)) then return less     (* pat1 < pat2*)
  1345.       elsif (id2  Classes (pat1)) then return greater  (* pat1 > pat2*)
  1346.       if NodesOfClass (id1)  NodesOfClass (id2) =  then
  1347.         return inconsistent            (* pat1 ~ pat2  *)
  1348.       else return independent          (* pat1 || pat2 *)
  1349.     elsif (type1 = class) then         (* B *)
  1350.       if (id1  Classes (pat2)) then return less        (* pat1 < pat2*)
  1351.       else
  1352.         common := (Subclasses (id1)U{id1})  ClassesOfNode (id2)
  1353.         if common =  then return inconsistent          (* pat1 || pat2*)
  1354.         else return independent        (* pat1 ~ pat2  *)
  1355.     elsif (type2 = class) then         (* C *)
  1356.       if (id2  Classes (pat1)) then return greater     (* pat1 > pat2*)
  1357.       else
  1358.         common :=  (Subclasses (id2)U{id2})  ClassesOfNode (id1)
  1359.         if common =  then return inconsistent          (* pat1 || pat2*)
  1360.         else return independent        (* pat1 ~ pat2  *)
  1361.  
  1362.  
  1363.  
  1364.  
  1365.  
  1366.  
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373.  
  1374.  
  1375.  
  1376.  
  1377.  
  1378.  
  1379.  
  1380.  
  1381.  
  1382.  
  1383.  
  1384.  
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391. 4.3. Beziehungen zwischen Mustern                                           23
  1392.  
  1393.  
  1394.  
  1395.     else                               (* D *)
  1396.       if id1 = id2 then
  1397.         relation := equal;             (* up to now: pat1 = pat2*)
  1398.         for pos := 1 to Arity (id1) do
  1399.           case Relation (Son (pat1, pos), Son (pat2, pos)) of
  1400.           | equal:
  1401.           | independent:
  1402.                 relation := independent                (* now: pat1 ~ pat2*)
  1403.           | inconsistent:
  1404.               return inconsistent      (* pat1 || pat2 *)
  1405.           | greater:
  1406.               if relation = equal
  1407.                 then relation := greater               (* now: pat1 > pat2*)
  1408.               elsif relation = less
  1409.                 then relation := independent           (* now: pat1 ~ pat2*)
  1410.           | less:
  1411.               if relation = equal
  1412.                 then relation := less  (* now: pat1 < pat2*)
  1413.               elsif relation = greater
  1414.                 then relation := independent           (* now: pat1 ~ pat2*)
  1415.         return relation
  1416.       else return inconsistent         (* pat1 || pat2 *)
  1417.     ______________________________________________________________________
  1418.  
  1419.     Abb. 4.5: Algorithmus zur Berechnung der Beziehung von zwei Mustern
  1420.  
  1421.  
  1422. Zu Beginn des Algorithmus Relation (Abb.  4.5)  werden  die  einfachen  Faelle
  1423. behandelt,  die  entstehen,  wenn eines der Muster oder beide Muster leer sind
  1424. (NoPat). Falls hier keine Entscheidung faellt, ist sichergestellt, dasz  beide
  1425. Muster eine Klasse oder einen Knoten als Wurzel enthalten.
  1426.  
  1427. Handelt es sich um zwei Klassen (A), so gilt  Gleichheit,  falls  die  Klassen
  1428. identisch  sind.  Trifft  dies  nicht  zu wird geprueft, ob ein Muster aus der
  1429. Klasse des anderen abgeleitet werden kann und somit kleiner  als  dieses  ist.
  1430. Zuletzt  wird  noch geprueft ob es Knoten gibt, die aus beiden Klassen hervor-
  1431. gehen koennen, die beiden Klassen werden dann als unabhaengig bezeichnet.  Bei
  1432. dieser  Festlegung  handelt es sich um einen Naeherung, denn tatsaechlich kann
  1433. hier (in pathologischen Faellen) auch jede andere Beziehung gelten. Im  uebri-
  1434. gen sind die Klassen und damit die Muster mit Sicherheit inkonsistent.
  1435.  
  1436. Bei den beiden naechsten Faellen (B, C) liegen jeweils  eine  Klasse  und  ein
  1437. Knoten  als  Wurzel  vor.  Kann  das  Muster mit dem Knoten als Wurzel aus der
  1438. Klasse abgeleitet werden, steht die Beziehung  fest.  Im  anderen  Falle  wird
  1439. geprueft  ob  es  ueberhaupt Muster gibt, die aus der Klasse abgeleitet werden
  1440. koennen und den Knoten als Wurzel haben,  denn  dann  werden  die  Muster  als
  1441. unabhaengig betrachtet. Ansonsten sind die beiden Muster inkonsistent.
  1442.  
  1443. Falls beide Muster einen Knoten als Wurzel haben (D),  gibt  es  zwei  Moegli-
  1444. chkeiten. Sind die beiden Knoten identisch, muessen die Soehne betrachtet wer-
  1445. den. Hierzu wird ein Hilfsvariable  (relation)  auf  gleich  (equal)  initial-
  1446. isiert.  Diese  Hilfsvariable  stellt  die  Beziehung der bereits betrachteten
  1447. Teile der beiden Muster dar. In Abhaengigkeit von den Beziehungen  der  Soehne
  1448.  
  1449.  
  1450.  
  1451.  
  1452.  
  1453.  
  1454.  
  1455.  
  1456.  
  1457.  
  1458. 24                                                                 4. Begriffe
  1459.  
  1460.  
  1461. wird  der  Wert  von  relation  gegebenenfalls angepaszt, bis spaetestens nach
  1462. Betrachten aller Soehne  das  Ergebnis  feststeht.   Sind  die  beiden  Knoten
  1463. hingegen verschieden, steht sofort Inkonsistenz fest.
  1464.  
  1465.  
  1466.  
  1467.  
  1468.  
  1469.  
  1470.  
  1471.  
  1472.  
  1473.  
  1474.  
  1475.  
  1476.  
  1477.  
  1478.  
  1479.  
  1480.  
  1481.  
  1482.  
  1483.  
  1484.  
  1485.  
  1486.  
  1487.  
  1488.  
  1489.  
  1490.  
  1491.  
  1492.  
  1493.  
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502.  
  1503.  
  1504.  
  1505.  
  1506.  
  1507.  
  1508.  
  1509.  
  1510.  
  1511.  
  1512.  
  1513.  
  1514.  
  1515.  
  1516.  
  1517.  
  1518.  
  1519.  
  1520.  
  1521.  
  1522.  
  1523.                                       25
  1524.  
  1525.  
  1526. 5.  Spezifikation von Transformationen mit ESTRAL
  1527.  
  1528. Im folgenden wird die Eingabesprache zur  Spezifikation  von  Transformationen
  1529. beschrieben.
  1530.  
  1531. 5.1.  Reservierte Woerter und Symbole
  1532.  
  1533. Die folgende Liste enthaelt die reservierten Woerter in ESTRAL:
  1534.  
  1535.     BEGIN, CLOSE, CONDITION, COSTS, DECLARE, EXPORT,
  1536.     FUNCTION, GLOBAL, GRAMMAR, TRANSFORMATION
  1537.  
  1538. Die Symbole
  1539.  
  1540.     (     )     {     }     ,     .     /     :     ;     =     |     ->
  1541.  
  1542. werden als Operatoren und Begrenzer verwendet.
  1543.  
  1544. 5.2.  Bezeichner
  1545.  
  1546. Bezeichner  (identifiers)  sind  Folgen  aus  Buchstaben  (letters),   Ziffern
  1547. (digits)  und  dem  Unterstreichungsstrich  (underscore).  Ein Bezeichner musz
  1548. immer mit einem Buchstaben beginnen.  Wenn reservierte Woerter als  Bezeichner
  1549. verwendet werden, sind sie mit einem '\' als Fluchtsymbol zu maskieren. Dieses
  1550. Fluchtsymbol, das auch vor jedem anderen Bezeichner stehen  darf,  ist  jedoch
  1551. nicht  Bestandteil  des Bezeichners, es dient lediglich zur Unterscheidung von
  1552. Schluesselwoertern und Bezeichnern.
  1553.  
  1554. Abb. 5.1 zeigt einen regulaeren Ausdruck, der  den  Aufbau  eines  Bezeichners
  1555. beschreibt.
  1556.  
  1557.  
  1558.     ______________________________________________________________________
  1559.  
  1560.     ident =     ['\'] letter (letter | digit | '_')*
  1561.     ______________________________________________________________________
  1562.  
  1563.     Abb. 5.1: regulaerer Ausdruck fuer Bezeichner
  1564.  
  1565.  
  1566. Beispiele fuer korrekte Bezeichner sind:
  1567.  
  1568.     Bezeichner, Doppel_Wort, \STOP, END, \BEGIN, A2, b4
  1569.  
  1570. Die folgende Zeichenfolgen sind hingegen keine gueltigen Bezeichner:
  1571.  
  1572.     BEGIN       (Schluesselwoerter sind nicht erlaubt)
  1573.     \\END       (nur ein ' \' ist erlaubt)
  1574.     4A          (Ziffer darf nicht am Anfang stehen)
  1575.     A-Z         (Bindestrich ist nicht erlaubt)
  1576.  
  1577. Bei der Verwendung von Bezeichnern ist auszerdem zu  beachten,  dasz  sie  vom
  1578. Generator  verwendet  werden,  um  Bezeichner fuer das Zielprogramm zu bilden.
  1579. Einschraenkungen, die in  der  Zielsprache  fuer  Bezeichner  gelten,  sollten
  1580.  
  1581.  
  1582.  
  1583.  
  1584.  
  1585.  
  1586.  
  1587.  
  1588.  
  1589.  
  1590. 26                            5. Spezifikation von Transformationen mit ESTRAL
  1591.  
  1592.  
  1593. deshalb unbedingt auch eingehalten werden.
  1594.  
  1595. Beispiele fuer solche Einschraenkungen sind das Verbot von '_' in  Bezeichnern
  1596. der Programmiersprache Modula-2 [Wir85] oder die Beschraenkung der signifikan-
  1597. ten Laenge von Bezeichnern in C [KeR83].
  1598.  
  1599. 5.3.  Zeichenketten
  1600.  
  1601. Zeichenketten (strings) sind  in  Anfuehrungszeichen  ('"')   oder  Apostrophe
  1602. ("'") eingeschlossene Zeichenfolgen. Die Zeichenfolge darf alle Zeichen auszer
  1603. dem Zeilenende und dem Begrenzer selbst enthalten.
  1604.  
  1605. 5.4.  Zahlen
  1606.  
  1607. Da nur positive ganze Zahlen benoetigt werden, genuegt  es,  Zahlen  (numbers)
  1608. als Folgen von Ziffern aufzufassen.
  1609.  
  1610. 5.5.  Kommentare
  1611.  
  1612. Kommentare koennen in den von Modula-2 und C gewohnten Formen geschrieben wer-
  1613. den,  so  dasz  es  moeglich  ist,  Kommentare  innerhalb  und  auszerhalb von
  1614. Quelltexten in der selben Weise zu schreiben.
  1615.  
  1616. 5.6.  Quelltext
  1617.  
  1618. Zur Darstellung von Bedingungen, Kosten, Vereinbarungen und  Anweisungen  wird
  1619. Quelltext  (source  text)  der  Zielsprache  verwendet.  Der Quelltext wird in
  1620. geschweifte Klammern eingeschlossen. Da dieser Text nicht immer direkt  ueber-
  1621. nommen werden kann, sondern zum Teil umgesetzt werden musz, sind einige Regeln
  1622. zu beachten, die es dem Generator erlauben, den Quelltext zu analysieren.
  1623.  
  1624. Kommentare, Zeichenketten und Bezeichner, die im Quelltext stehen, werden  als
  1625. Einheiten  betrachtet,  die  nicht  weiter  untergliedert werden.  Geschweifte
  1626. Klammern duerfen innerhalb des Quelltextes nur paarweise auftreten, damit  das
  1627. Ende  des  Quelltextes  erkennbar  ist. Klammern innerhalb von Kommentaren und
  1628. Zeichenketten werden hierbei natuerlich nicht mitgezaehlt.
  1629.  
  1630. Obwohl diese Regeln so gewaehlt wurden, dasz sie beim Schreiben von  Quelltex-
  1631. ten  moeglichst wenig einschraenken, gibt es einige Fehlerquellen, auf die man
  1632. achten sollte.
  1633.  
  1634. So darf folgendes  korrekte  C-Programmfragment  keinesfalls  in  dieser  Form
  1635. geschrieben werden.
  1636.  
  1637.     { i = 3 * (*p + i); }
  1638.  
  1639. Die Folge waere, dasz ein  (nicht  geschlossener)  Modula-2-Kommentar  erkannt
  1640. wuerde.  Doch kann dieses Problem leicht beseitigt werden, indem man ein Leer-
  1641. zeichen zur Trennung der Klammer und des Adreszoperators benutzt.
  1642.  
  1643.     { i = 3 * ( *p + i) }
  1644.  
  1645. Nun kann nicht mehr faelschlich ein Kommentar erkannt werden.
  1646.  
  1647.  
  1648.  
  1649.  
  1650.  
  1651.  
  1652.  
  1653.  
  1654.  
  1655.  
  1656. 5.6. Quelltext                                                              27
  1657.  
  1658.  
  1659. Weitere Probleme koennen  bei  Zeichenketten  in  C  entstehen,  da  sich  die
  1660. Festlegung der Schreibweise von Zeichenketten an den Konventionen von Modula-2
  1661. orientierte.
  1662.  
  1663.     { c = '\''; }
  1664.     { printf ("\""; }
  1665.  
  1666. Solche Eingaben fuehren zu Fehlermeldungen, da jeweils eine nicht geschlossene
  1667. Zeichenkette erkannt wird.
  1668.  
  1669. 5.7.  Transformation
  1670.  
  1671. Die Beschreibung einer Transformation (Abb. 5.2) besteht aus einer Baumgramma-
  1672. tik  (grammar),  zur Beschreibung der Struktur der zu transformierenden Baeume
  1673. und mehreren  Funktionen  (function),  die  die  Abbildung  beschreiben.   Die
  1674. Integration  des generierten Programms in eine Umgebung wird in einem weiteren
  1675. Abschnitt (integration) beschrieben.
  1676.  
  1677.  
  1678.     ______________________________________________________________________
  1679.  
  1680.  
  1681.     transformation   =   TRANSFORMATION
  1682.                            ident          Name der Transformation
  1683.                            integration    Integration
  1684.                            grammar        Baumgrammatik
  1685.                            function *     Funktionen
  1686.  
  1687.     __________________________________________________________________________
  1688.  
  1689.     Abb. 5.2: Transformation
  1690.  
  1691.  
  1692. Um mehrere Transformationen unterscheiden zu koennen, wird  jeder  Transforma-
  1693. tion ein Name zugeordnet.
  1694.  
  1695. 5.8.  Baumgrammatik
  1696.  
  1697. Die Baumgrammatik wird benutzt, um die  Struktur  der  zulaessigen  Baeume  zu
  1698. beschreiben  und  bildet  die  Grundlage  fuer alle Konsistenzpruefungen (vgl.
  1699. 4.1.) denen die Eingabe unterzogen wird.
  1700.  
  1701.  
  1702.     ______________________________________________________________________
  1703.  
  1704.  
  1705.     grammar   =   GRAMMAR
  1706.                     ident     Name der Grammatik
  1707.                     class *   Beschreibung der Klassen
  1708.  
  1709.     __________________________________________________________________________
  1710.  
  1711.     Abb. 5.3: Baumgrammatik
  1712.  
  1713.  
  1714. Der Name der Grammatik wird in der Implementierung benutzt, um das Modul,  das
  1715.  
  1716.  
  1717.  
  1718.  
  1719.  
  1720.  
  1721.  
  1722.  
  1723.  
  1724.  
  1725. 28                            5. Spezifikation von Transformationen mit ESTRAL
  1726.  
  1727.  
  1728. die Baeume realisiert, zu bezeichnen. Die eigentliche Grammatik wird mit Hilfe
  1729. der Klassen beschrieben.
  1730.  
  1731. 5.9.  Klassen
  1732.  
  1733. Klassen werden durch  einen  Bezeichner,  dem  ein  Gleichheitszeichen  folgt,
  1734. definiert. Zusammen mit den Klassen werden auch die Produktionen der Baumgram-
  1735. matik festgelegt. Die Kettenproduktionen koennen aufgrund des Oberklassenprin-
  1736. zips  (vgl. Kapitel 4) durch die optionale Angabe einer Oberklasse beschrieben
  1737. werden.  Die  Knotenproduktionen  werden  beschrieben,  indem   alle   Knoten-
  1738. beschreibungen bei der zugehoerigen Klasse aufgezaehlt werden.
  1739.  
  1740.  
  1741.     ______________________________________________________________________
  1742.  
  1743.  
  1744.     class   =   [ ident '->' ]   Bezeichner der Oberklasse
  1745.                   ident '='      Bezeichner der Klasse
  1746.                   node *         Knotenbeschreibungen
  1747.  
  1748.     __________________________________________________________________________
  1749.  
  1750.     Abb. 5.4: Klassen
  1751.  
  1752.  
  1753.  
  1754. 5.10.  Knoten
  1755.  
  1756. Die Knotenbeschreibung ordnet dem Knoten einen Namen in Form  einer  Zeichenk-
  1757. ette oder eines Bezeichners zu und zaehlt seine Soehne auf.
  1758.  
  1759.  
  1760.     ______________________________________________________________________
  1761.  
  1762.  
  1763.     node   =   '|' (string | ident)       Name des Knotens
  1764.                  [ ':' ident ]            Bezeichner des Knotens (siehe Hauptbeschreibung)
  1765.                  '(' [ son || ',' ] ')'   Soehne
  1766.  
  1767.     __________________________________________________________________________
  1768.  
  1769.     Abb. 5.5: Knoten
  1770.  
  1771.  
  1772. Beispiele:
  1773.  
  1774.     | '+'     : Plus    (e1: expr, e2: expr)
  1775.     | ':='    : Asgn    (index, expr)
  1776.     | While        (expr, then: stats, else: stats)
  1777.     | Const        ()
  1778.  
  1779.  
  1780. 5.11.  Soehne
  1781.  
  1782. Um den Sohn eines Knotens festzulegen, wird seine Klasse angegeben.
  1783.  
  1784.  
  1785.  
  1786.  
  1787.  
  1788.  
  1789.  
  1790.  
  1791.  
  1792.  
  1793. 5.11. Soehne                                                                29
  1794.  
  1795.  
  1796.  
  1797.     ______________________________________________________________________
  1798.  
  1799.  
  1800.     son   =   [ ident ':' ]   Name des Sohnes (nur in der Hauptbeschreibung)
  1801.                 ident         Klasse des Sohnes
  1802.     __________________________________________________________________________
  1803.  
  1804.     Abb. 5.6: Soehne
  1805.  
  1806.  
  1807.  
  1808. Beispiele:
  1809.  
  1810.     expr
  1811.     e1: expr
  1812.     const
  1813.  
  1814.  
  1815.  
  1816.  
  1817.  
  1818.  
  1819.  
  1820.  
  1821.  
  1822.  
  1823.  
  1824.  
  1825.  
  1826.  
  1827.  
  1828.  
  1829.  
  1830.  
  1831.  
  1832.  
  1833.  
  1834.  
  1835.  
  1836.  
  1837.  
  1838.  
  1839.  
  1840.  
  1841.  
  1842.  
  1843.  
  1844.  
  1845.  
  1846.  
  1847.  
  1848.  
  1849.  
  1850.  
  1851.  
  1852.  
  1853.  
  1854.  
  1855.  
  1856.  
  1857.  
  1858.  
  1859.  
  1860.                                       1
  1861.  
  1862.  
  1863. Inhaltsverzeichnis
  1864.  
  1865. 1. Einleitung ...........................................................    4
  1866.  
  1867. 2. Moeglichkeiten zur Beschreibung von Transformationen .................    5
  1868.    2.1.     Attributierte Grammatiken ...................................    5
  1869.    2.2.     Modifikation der Eingabe ....................................    5
  1870.    2.3.     Funktionale Abbildung .......................................    6
  1871.  
  1872. 3. Anforderungen an eine funktionale Beschreibung .......................    7
  1873.    3.1.     Abbildung der einzelnen Knoten ..............................    7
  1874.    3.2.     Steuerung der Reihenfolge ...................................    8
  1875.    3.3.     Zugriff auf die Attribute ...................................    8
  1876.    3.4.     Berechnung eines synthetisierten Attributs ..................    9
  1877.    3.5.     Muster ......................................................   10
  1878.    3.6.     Mehrdeutigkeit und Kosten ...................................   11
  1879.    3.7.     Bedingungen .................................................   12
  1880.    3.8.     Mehrfachtransformation ......................................   13
  1881.    3.9.     Synthetisierte und vererbte Attribute .......................   14
  1882.  
  1883. 4. Begriffe .............................................................   17
  1884.    4.1.     Baumgrammatik ...............................................   17
  1885.    4.2.     Muster ......................................................   19
  1886.    4.3.     Beziehungen zwischen Mustern ................................   20
  1887.  
  1888. 5. Spezifikation von Transformationen mit ESTRAL ........................   25
  1889.    5.1.     Reservierte Woerter und Symbole .............................   25
  1890.    5.2.     Bezeichner ..................................................   25
  1891.    5.3.     Zeichenketten ...............................................   26
  1892.    5.4.     Zahlen ......................................................   26
  1893.    5.5.     Kommentare ..................................................   26
  1894.    5.6.     Quelltext ...................................................   26
  1895.    5.7.     Transformation ..............................................   27
  1896.    5.8.     Baumgrammatik ...............................................   27
  1897.    5.9.     Klassen .....................................................   28
  1898.    5.10.    Knoten ......................................................   28
  1899.    5.11.    Soehne ......................................................   28
  1900.  
  1901.  
  1902.  
  1903.  
  1904.  
  1905.  
  1906.  
  1907.  
  1908.  
  1909.  
  1910.  
  1911.  
  1912.  
  1913.  
  1914.  
  1915.  
  1916.  
  1917.  
  1918.  
  1919.  
  1920.  
  1921.  
  1922.  
  1923.  
  1924.  
  1925.                                       28
  1926.  
  1927.  
  1928. 5.12.  Hauptbeschreibung
  1929.  
  1930. Aufgrund des in Kapitel 4.1. geforderten Prinzips der Hauptbeschreibung,  musz
  1931. fuer  jeden  Knoten eine Hauptbeschreibung existieren. Diese Hauptbeschreibung
  1932. hat neben ihrer Funktion als Knotenproduktion der Baumgrammatik  die  Aufgabe,
  1933. die Implementierung des Knotens zu beschreiben. In der Hauptbeschreibung eines
  1934. Knotens werden deshalb der Bezeichner des Knotens (Abb. 5.5) und die Namen der
  1935. Klassen  (Abb. 5.6) festgelegt. Diese werden in der Implementierung verwendet,
  1936. um auf den Knoten, dessen Attribute und Soehne zuzugreifen  und  die  Art  des
  1937. Knotens  festzustellen  (vgl. Kapitel 9.1.).  Falls keine explizite Festlegung
  1938. erfolgt, wird der Bezeichner des Knotens mit seinem Namen und  die  Namen  der
  1939. Soehne mit den Klassen gleichgesetzt.  Klassen gleichgesetzt.
  1940.  
  1941. 5.13.  Funktionen
  1942.  
  1943. Die Funktionen beschreiben die Abbildung, die durch die  Transformation  real-
  1944. isiert werden soll.
  1945.  
  1946. Die Beschreibung einer  Funktion  (function)  (Abb.  5.7)  umfaszt  den  Namen
  1947. (ident)  der  Funktion,  die  Beschreibung  der  vererbten und synthetisierten
  1948. Attribute (attributes),  die  Festlegung  des  Ergebnistyps  und  des  Defini-
  1949. tionsbereichs,  sowie Vorschriften (directive) zur Durchfuehrung der Transfor-
  1950. mation.
  1951.  
  1952.  
  1953.     ______________________________________________________________________
  1954.  
  1955.  
  1956.     Function   =   FUNCTION
  1957.                      ident                            Name der Funktion
  1958.                      [ attributes '->' attributes ]   vererbte und synthetisierte Attribute
  1959.                      [ ':' type ]                     Ergebnistyp
  1960.                      domain                           Definitionsbereich
  1961.                      directive *                      Vorschriften zur Beschreibung der Funktion
  1962.  
  1963.     __________________________________________________________________________
  1964.  
  1965.     Abb. 5.7: Funktionen
  1966.  
  1967.  
  1968. Die Transformation wird durchgefuehrt, indem die erste  Funktion  auf  den  zu
  1969. transformierenden  Baum angewandt wird. Der Definitionsbereich der Transforma-
  1970. tion kann deshalb mit dem Definitionsbereich der ersten Funktion gleichgesetzt
  1971. werden.
  1972.  
  1973. Die Vollstaendigkeit wird in der in Kapitel 8 beschriebenen Weise ueberprueft.
  1974.  
  1975. 5.14.  Typen
  1976.  
  1977. Typen (Abb. 5.8) werden durch einen Bezeichner wie z.B.
  1978.  
  1979.      INTEGER, REAL, BOOLEAN
  1980.  
  1981.  
  1982.  
  1983.  
  1984.  
  1985.  
  1986.  
  1987.  
  1988.  
  1989.  
  1990.  
  1991.  
  1992. 5.14. Typen                                                                 29
  1993.  
  1994.  
  1995. beschrieben.
  1996.  
  1997. Um  einen  qualifizierten  Import,  wie  er  in  Modula-2  moeglich  ist,   zu
  1998. beschreiben,  kann ein weitere Bezeichner verwendet werden, um das Modul fest-
  1999. zulegen.  Damit sind auch Angaben der Form
  2000.  
  2001.      SYSTEM.TSIZE, Sets.tSet, IO.WriteS
  2002.  
  2003. moeglich.
  2004.  
  2005.  
  2006.     ______________________________________________________________________
  2007.  
  2008.  
  2009.     type   =   [ ident '.' ]   Angabe des Moduls zur Qualifikation
  2010.                  ident         Bezeichner des Typs
  2011.  
  2012.     __________________________________________________________________________
  2013.  
  2014.     Abb. 5.8: Typen
  2015.  
  2016.  
  2017.  
  2018. 5.15.  Attribute
  2019.  
  2020. Die Angabe der Attribute ist optional. Einzelne Attribute werden  durch  einen
  2021. Bezeichner  und einen Typ beschrieben. Um mehrere Attribute des selben Typs zu
  2022. beschreiben, werden die Bezeichner, durch Komma  getrennt,  aufgezaehlt.  Wenn
  2023. Attribute  mit  unterschiedlichen Typen beschrieben werden, sind die einzelnen
  2024. Beschreibungen durch Strichpunkte zu trennen.
  2025.  
  2026.  
  2027.     ______________________________________________________________________
  2028.  
  2029.  
  2030.     attributes   =   [ ( (ident || ','   Liste von Bezeichnern
  2031.                        ':' type)         Angabe des Typs
  2032.                        || ';' ) ]         mehrere solche Listen durch ';' getrennt
  2033.  
  2034.     __________________________________________________________________________
  2035.  
  2036.     Abb. 5.9: Attribute
  2037.  
  2038.  
  2039.  
  2040. Beispiel:
  2041.  
  2042.      A: INTEGER; B,C: REAL
  2043.  
  2044. 5.16.  Definitionbereich
  2045.  
  2046. Der Definitionsbereich (domain) einer  Funktion  wird  festgelegt,  indem  die
  2047. Klassen (ident), fuer die die Funktion definiert ist, aufgezaehlt werden.
  2048.  
  2049.  
  2050.  
  2051.  
  2052.  
  2053.  
  2054.  
  2055.  
  2056.  
  2057.  
  2058.  
  2059.  
  2060.                                       30
  2061.  
  2062.  
  2063.  
  2064.     ______________________________________________________________________
  2065.  
  2066.  
  2067.     domain   =   '/' ident || ',' '/'   Liste von Klassen
  2068.  
  2069.     __________________________________________________________________________
  2070.  
  2071.     Abb. 5.10: Definitionsbereich
  2072.  
  2073.  
  2074. Beispiel:
  2075.  
  2076.     / stats, expr /
  2077.  
  2078. Der Definitionsbereich der ersten Funktion  legt  auszerdem  die  Startsymbole
  2079. fest  und  bildet somit die Basis fuer die Ueberpruefung der Reduziertheit der
  2080. Grammatik (vgl. 4.1.).
  2081.  
  2082. 5.17.  Vorschriften
  2083.  
  2084. Die Vorschriften (directive), die die Abbildungen  im  einzelnen  beschreiben,
  2085. bestehen  im  einfachsten  Falle aus einem Muster (pattern), das festlegt, auf
  2086. welche (Teil-) Baeume die Vorschrift angewandt  werden  kann  und  Anweisungen
  2087. (instructions), die festlegen, wie der betreffende (Teil-) Baum behandelt wer-
  2088. den musz.
  2089.  
  2090.  
  2091.     ______________________________________________________________________
  2092.  
  2093.  
  2094.     directive   =   pattern              Muster
  2095.                       [ condition ]      Bedingung
  2096.                       [ costs ]          Kosten
  2097.                       [ declarations ]   lokale Vereinbarungen
  2098.                       instructions       Anweisungen
  2099.  
  2100.     __________________________________________________________________________
  2101.  
  2102.     Abb. 5.11: Vorschriften
  2103.  
  2104.  
  2105.  
  2106. 5.18.  Muster
  2107.  
  2108. Das Muster beschreibt einen Ausschnitt des  Baumes,  der  in  den  Anweisungen
  2109. bearbeitet  wird.  Mit  Hilfe  der Selektoren kann in den Vorschriften auf die
  2110. entsprechenden Knoten des Strukturbaumes zugegriffen  werden.  Die  Selektoren
  2111. werden, falls sie nicht explizit angegeben sind, aus den Namen der Knoten bzw.
  2112. Klassen abgeleitet. Falls es hierbei zu Mehrdeutigkeit kommt, liegt ein Fehler
  2113. vor.  Die  automatische  Erzeugung eines Selektors wird unterdrueckt, wenn ein
  2114. Doppelpunkt angegeben wird, dem kein Bezeichner vorangestellt  ist.  Wenn  auf
  2115. spezielle  Knoten  in  den  Anweisungen nicht zugegriffen werden musz, koennen
  2116. durch die Unterdrueckung Mehrdeutigkeiten vermieden werden.
  2117.  
  2118.  
  2119.  
  2120.  
  2121.  
  2122.  
  2123.  
  2124.  
  2125.  
  2126.  
  2127.  
  2128. 5.18. Muster                                                                31
  2129.  
  2130.  
  2131.  
  2132.     ______________________________________________________________________
  2133.  
  2134.  
  2135.     pattern   =   [ [ ident ] ':' ]              Selektor
  2136.                     (ident | string)             Name des Knotens
  2137.                     '(' [ pattern || ',' ] ')'   Soehne
  2138.               |   [ ident ] ':'                  Selektor
  2139.                     [ ident ]                    Bezeichner der Klasse
  2140.               |   ident                          Selektor und Bezeichner der Klasse
  2141.  
  2142.     __________________________________________________________________________
  2143.  
  2144.     Abb. 5.12: Muster
  2145.  
  2146.  
  2147. Beispiele:
  2148.  
  2149.     '+' (e1:, e2:)
  2150.     ':=' (index, expr)
  2151.     If (expr, then:, else:)
  2152.     :'+' (:'+' (e1: const, e2: const), e3:)
  2153.     expr
  2154.     const
  2155.  
  2156.  
  2157. 5.19.  Anweisungen
  2158.  
  2159.  
  2160.     ______________________________________________________________________
  2161.  
  2162.  
  2163.     instructions   =   '{' source_text '}'
  2164.  
  2165.     __________________________________________________________________________
  2166.  
  2167.     Abb. 5.13: Anweisungen
  2168.  
  2169.  
  2170.  
  2171. Die Anweisungen (instructions) sind der Kern jeder Vorschrift, sie werden  vom
  2172. Transformator ausgefuehrt, wenn die Vorschrift angewandt wird.
  2173.  
  2174. Zum Zugriff auf den durch das Muster beschriebenen Teil des Baumes koennen die
  2175. Selektoren  des  Musters  verwendet werden, wobei zwei Faelle zu unterscheiden
  2176. sind. Folgt dem Selektor ein Punkt, wird ein Zugriff auf ein Attribut angenom-
  2177. men und der Selektor wird automatisch durch den Zugriff auf den entsprechenden
  2178. Knoten im Baum ersetzt. Folgt kein Punkt, wird der Selektor durch einen Zeiger
  2179. auf den Baum ersetzt.
  2180.  
  2181. Bei Funktionsaufrufen innerhalb der Vorschrift sollte das erste Argument,  das
  2182. den zu transformierenden Baum beschreibt, normalerweise eine Selektor sein, da
  2183. nur dann vom Generator geprueft  werden  kann,  ob  das  Argument  im  Defini-
  2184. tionsbereich liegt. Da es jedoch in speziellen Faellen zweckmaeszig ist, einen
  2185. Baum zu transformieren, der durch ein  vererbtes  Attribut  beschrieben  wird,
  2186. wird  es  auch  akzeptiert, wenn der zu transformierende Baum auf andere Weise
  2187.  
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.                                       32
  2198.  
  2199.  
  2200. spezifiziert wird.
  2201.  
  2202. 5.20.  Bedingungen
  2203.  
  2204. Um die Anwendbarkeit einer Vorschrift  einzuschraenken,  kann  eine  Bedingung
  2205. (condition)  an die Attribute gestellt werden.  Eine Bedingung wird durch eine
  2206. booleschen Ausdruck in Form von Quelltext beschrieben.
  2207.  
  2208. Selektoren koennen in den Bedingungen ebenfalls verwendet werden.
  2209.  
  2210. Der Aufruf von Funktionen und Prozeduren ist in Bedingungen  prinzipiell  moe-
  2211. glich, die verwendeten Funktionen sollten jedoch keine Seiteneffekte haben, da
  2212. die Reihenfolge, in der die Bedingungen getestet werden nicht festgelegt  ist.
  2213. Auszerdem  darf  keine Funktion fuer die Wurzel des Musters aufgerufen werden,
  2214. da die Vorschrift  die  hierzu  benoetigt  wird,  von  eben  dieser  Bedingung
  2215. abhaengen koennte.
  2216.  
  2217.  
  2218.     ______________________________________________________________________
  2219.  
  2220.  
  2221.     condition   =   CONDITION
  2222.                       '{' source_text '}'   Ausdruck zur Berechnung der Bedingung
  2223.  
  2224.     __________________________________________________________________________
  2225.  
  2226.     Abb. 5.14: Bedingungen
  2227.  
  2228.  
  2229. Beispiel:
  2230.  
  2231.     '*' (expr, const)   CONDITION { IsPowerOf2 (const.value) }
  2232.               {
  2233.               ...
  2234.               }
  2235.  
  2236.  
  2237. 5.21.  Kosten
  2238.  
  2239. Um die Kosten, die bei Anwendung eine Vorschrift  entstehen,  zu  beschreiben,
  2240. gibt  es zwei Moeglichkeiten.  Die Kosten werden entweder durch eine Konstante
  2241. (number) festgelegt oder es wird ein Ausdruck (source text) angegeben, die die
  2242. Kosten  fuer  den  gesamten  durch  das Muster abgedeckten Baum berechnen.  Im
  2243. ersten Fall werden  die  Kosten,  die  durch  Funktionsaufrufe  innerhalb  der
  2244. Vorschriften  verursacht werden, automatisch mit einfacher Gewichtung berueck-
  2245. sichtigt.  Im zweiten Fall ist dies Aufgabe des Anwenders.
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264. 5.21. Kosten                                                                33
  2265.  
  2266.  
  2267.  
  2268.     ______________________________________________________________________
  2269.  
  2270.  
  2271.     costs   =   COSTS
  2272.                   (number                  Beschreibung der Kosten durch eine Konstante
  2273.                   | '{' source_text '}')   Ausdruck zur Berechnung der Kosten
  2274.  
  2275.     __________________________________________________________________________
  2276.  
  2277.     Abb. 5.15: Kosten
  2278.  
  2279.  
  2280. Um diese Kosten zu beruecksichtigen, stehen dem Anwender Prozeduren  zur  Ver-
  2281. fuegung, die die Kosten fuer eine bestimmte Funktion liefern. Die Namen dieser
  2282. Prozeduren setzen sich aus dem Wort 'Cost' und dem Name der betreffenden Funk-
  2283. tion  zusammen. Als einziges Argument wird der Selektor des betreffenden Teil-
  2284. baums erwartet.
  2285.  
  2286. Beispiel:
  2287.  
  2288.     '+' (e1: expr, e2:expr) COSTS   { 1 + 2 * CostF (e1) + CostF (e2) }
  2289.                                             {
  2290.                                             ...  F (e1); ...  F (e2); ...
  2291.                                             }
  2292.  
  2293. Falls die Kosten nicht explizit angegeben werden, wird COSTS 1 angenommen.
  2294.  
  2295. 5.22.  Vereinbarungen
  2296.  
  2297. Die Vereinbarungen (declarations) sind lokal d.h.  nur  fuer  die  Anweisungen
  2298. einer  Vorschrift  sichtbar.  Sie koennen z.B. benutzt werden, um Variablen zu
  2299. vereinbaren, die nur in den Anweisungen einer Vorschrift benoetigt werden.
  2300.  
  2301.  
  2302.     ______________________________________________________________________
  2303.  
  2304.  
  2305.     declarations   =   DECLARE '{' source_text '}'
  2306.  
  2307.     __________________________________________________________________________
  2308.  
  2309.     Abb. 5.16: Vereinbarungen
  2310.  
  2311.  
  2312. Beispiel:
  2313.  
  2314.     DECLARE {
  2315.     VAR I,J: INTEGER;
  2316.     }
  2317.  
  2318.  
  2319. 5.23.  Integration
  2320.  
  2321. Die optionalen EXPORT-, LOCAL-, BEGIN- und CLOSE-Abschnitte werden  verwendet,
  2322. um  das  generierte  Programm in die Umgebung zu integrieren. Der Quelltext im
  2323.  
  2324.  
  2325.  
  2326.  
  2327.  
  2328.  
  2329.  
  2330.  
  2331.  
  2332.  
  2333.                                       34
  2334.  
  2335.  
  2336. EXPORT-Abschnitt dient zur Vereinbarung globaler Daten,  die  auch  auszerhalb
  2337. des  generierten Programms sichtbar sein sollen. Der GLOBAL-Abschnitt enthaelt
  2338. von auszen nicht sichtbare globale Vereinbarungen. Die Anweisungen  im  BEGIN-
  2339. Abschnitt  werden  vor  der Transformation ausgefuehrt, die im CLOSE-Abschnitt
  2340. danach. Der Zweck der beiden letzten Abschnitte besteht darin,  globale  Daten
  2341. zu   initialisieren,  bevor  eine  Transformation  durchgefuehrt  wird,  sowie
  2342. Abschluszarbeiten (z.B.  Speicherbereinigung oder Schlieszen von Dateien) dur-
  2343. chzufuehren, nachdem die Transformation abgeschlossen ist.
  2344.  
  2345.  
  2346.     ______________________________________________________________________
  2347.  
  2348.  
  2349.  
  2350.     integration   =   [ EXPORT '{' source_text '}' ]   oeffentliche Vereinbarungen
  2351.                       [ GLOBAL '{' source_text '}' ]   globale Vereinbarungen
  2352.                       [ BEGIN '{' source_text '}' ]    Anweisungen zur Initialisierung
  2353.                       [ CLOSE '{' source_text '}' ]    Anweisungen zum Abschlusz
  2354.  
  2355.     __________________________________________________________________________
  2356.  
  2357.     Abb. 5.17: Integration
  2358.  
  2359.  
  2360.  
  2361.  
  2362.  
  2363.  
  2364.  
  2365.  
  2366.  
  2367.  
  2368.  
  2369.  
  2370.  
  2371.  
  2372.  
  2373.  
  2374.  
  2375.  
  2376.  
  2377.  
  2378.  
  2379.  
  2380.  
  2381.  
  2382.  
  2383.  
  2384.  
  2385.  
  2386.  
  2387.  
  2388.  
  2389.  
  2390.  
  2391.  
  2392.  
  2393.  
  2394.  
  2395.  
  2396.  
  2397.  
  2398.  
  2399.  
  2400.                                       35
  2401.  
  2402.  
  2403. 6.  Implementierung von Transformationen durch ESTRA
  2404.  
  2405. Im folgenden werden die Struktur von mit ESTRA erzeugten  Transformatoren  und
  2406. deren  wesentliche  Eigenschaften  beschrieben.  Es  kann jedoch nicht Aufgabe
  2407. diese Kapitels sein, saemtliche Details  der  erzeugten  Implementierungen  zu
  2408. besprechen.  Diese  Details kann der interessierte Leser im Anhang B.2 finden.
  2409. Das Beispiel im Anhang ist ueberdies geeignet, die folgenden Ausfuehrungen  zu
  2410. ergaenzen.
  2411.  
  2412. Mit ESTRA  generierte  Transformatoren  fuehren  die  Transformation  in  zwei
  2413. Schritten  durch.  Im  ersten  Schritt  (Vorbereitung) wird festgelegt, welche
  2414. Vorschriften zur Transformation des speziellen Baumes im einzelnen  anzuwenden
  2415. sind. Im zweiten Schritt (Durchfuehrung) werden diese Vorschriften angewandt.
  2416.  
  2417. Zur Vorbereitung der Transformation werden in  jedem  Knoten  des  Baumes  die
  2418. Vorschriften  mit  den geringsten Kosten fuer die Durchfuehrung einer Funktion
  2419. festgehalten. Um diese Vorschriften zu ermitteln, ist es notwendig, fuer  jede
  2420. Vorschrift  zu  pruefen,  ob das Muster auf den Knoten paszt und die Bedingung
  2421. (sofern vorhanden) erfuellt ist.  Dann musz fuer jede Funktion  von  den  ver-
  2422. bliebenen  Vorschriften  diejenige  mit  den geringsten Kosten im Knoten fest-
  2423. gehalten werden.
  2424.  
  2425. Da die Kosten fuer die Anwendung einer Vorschrift im allgemeinen von den  Kos-
  2426. ten  der  Soehne  (bzw.  'Nachkommen')  des Knotens abhaengig sind, musz diese
  2427. Berechnung in einem Bottom-Up-Durchlauf durch den Baum erfolgen.
  2428.  
  2429. Die Durchfuehrung der Transformation erfolgt durch Anwendung der ersten  Funk-
  2430. tion  auf  die Wurzel, d.h. die Vorschrift, die in der Wurzel fuer diese Funk-
  2431. tion festgehalten wurde, wird ausgefuehrt.  Funktionsaufrufe fuer  Teilbaeume,
  2432. die  bei  der  Abarbeitung  einer Vorschrift anfallen, werden rekursiv abgear-
  2433. beitet.
  2434.  
  2435. 6.1.  Vorbereitung der Transformation
  2436.  
  2437. Bevor die Transformation in der obengenannten Weise durchgefuehrt werden kann,
  2438. musz  sie  durch  die  Festlegung der Loesung mit minimalen Kosten vorbereitet
  2439. werden.
  2440.  
  2441. Die Vorbereitung entspricht einer S-Attributierung, bei der fuer jeden  Knoten
  2442. die folgenden Attribute berechnet werden:
  2443.  
  2444. 1.   die Menge der Klassen, zu denen der Knoten gehoert
  2445.  
  2446. 2.   die Vorschriften, die auf den Knoten (genauer dessen Teilbaum)  anwendbar
  2447.      sind
  2448.  
  2449. 3.   fuer jede Funktion die Vorschrift, die diese mit  den  geringsten  Kosten
  2450.      realisiert und die hierbei entstehenden Kosten
  2451.  
  2452. Die rekursive Prozedur yyTraverse, die diese Attribute berechnet, hat  folgen-
  2453. den Aufbau:
  2454.  
  2455.  
  2456.  
  2457.  
  2458.  
  2459.  
  2460.  
  2461.  
  2462.  
  2463.  
  2464.  
  2465. 36                         6. Implementierung von Transformationen durch ESTRA
  2466.  
  2467.  
  2468. 1.   Beschaffung von Speicher fuer die Attribute
  2469.  
  2470. 2.   Prozeduraufrufe zur Berechnung der Attribute der Soehne des Knotens
  2471.  
  2472. 3.   Berechnung der Klassen des aktuellen Teilbaums
  2473.  
  2474. 4.   Berechnung der zulaessigen Vorschriften
  2475.  
  2476. 5.   Berechnung der kostenguenstigsten Vorschrift  fuer  die  einzelnen  Funk-
  2477.      tionen
  2478.  
  2479. 6.2.  Darstellung von Funktionen und Vorschriften
  2480.  
  2481. In Modula-2 [Wir85] werden sowohl die Funktionen  als  auch  die  Vorschriften
  2482. (genauer  die  Vereinbarungen und Anweisungen der Vorschriften) als Prozeduren
  2483. realisiert. Die Prozeduren, die den Funktionen  entsprechen,  waehlen  hierbei
  2484. lediglich  die  Vorschrift  aus  und rufen die entsprechende Prozedur auf. Das
  2485. bedeutet, dasz bei der Durchfuehrung einer Transformation fuer jede  Anwendung
  2486. einer  Vorschrift  zwei  Prozeduraufrufe notwendig sind. Besser waere es, wenn
  2487. man mit je einem Aufruf auskaeme.
  2488.  
  2489. Um dies zu erreichen gibt es  zwei  Moeglichkeiten.  Entweder  man  spart  die
  2490. Prozeduren der Funktionen, d.h. die Auswahl der Vorschrift wird an den Ort des
  2491. Funktionsaufrufs  verschoben,  oder  man  spart  die   Prozeduren   fuer   die
  2492. Vorschriften, d.h. alle Vorschriften einer Funktion werden in die Prozedur der
  2493. Funktion eingebettet.
  2494.  
  2495. Die Information, welche Vorschriften im einzelnen anzuwenden sind, wird  nicht
  2496. unmittelbar in den Knoten gespeichert. Es ist vielmehr so, dasz dort lediglich
  2497. eine Adresse zu finden ist, die einen Verweis auf diese Information  darstellt
  2498. (vgl.  Kapitel  9).   Infolgedessen  ist vor dem Zugriff auf diese Information
  2499. eine Typwandlung, die die Adresse in  den  erforderlichen  Zeigertyp  wandelt,
  2500. notwendig.
  2501.  
  2502. Um aber in Modula-2 eine Adresse in  einen  Zeiger  umzuwandeln  und  auf  die
  2503. zugehoerige  Information  ueber  diesen Zeiger zuzugreifen, ist eine Zuweisung
  2504. erforderlich. Dies bedeutet, dasz beim Verschieben der Auswahl an den Ort  des
  2505. Funktionsaufrufs  fuer  jeden  Aufruf  eine zusaetzliche Anweisung, eben diese
  2506. Zuweisung, erforderlich ist. Da  der  Aufwand,  diese  Anweisung  in  die  vom
  2507. Anwender  vorgegebenen Anweisungen einzufuegen, recht grosz waere, wurde diese
  2508. Moeglichkeit verworfen.
  2509.  
  2510. Die zweite Moeglichkeit, die darin besteht, alle Vorschriften  einer  Funktion
  2511. in  eine  Prozedur  zu  packen,  scheitert in Modula-2 daran, dasz die lokalen
  2512. Vereinbarungen, die zu den einzelnen Vorschriften gehoeren, in der Regel nicht
  2513. in  einer Prozedur untergebracht werden koennen, da es sonst zu Namenskonflik-
  2514. ten zwischen diesen Vereinbarungen kommt.
  2515.  
  2516. In der Programmiersprache C [KeR83] sind hingegen beide Loesung  realisierbar,
  2517. da  weder  die Typwandlung (type cast) noch die Vereinbarung von lokalen Daten
  2518. (innerhalb von Bloecken) Probleme  darstellen.  Da  bei  der  zweiten  Loesung
  2519. insgesamt  weniger  Funktionen  (die Unterprogramme in C werden als Funktionen
  2520. bezeichnet) benoetigt werden und bei dieser Loesung auszerdem weniger  Aufwand
  2521.  
  2522.  
  2523.  
  2524.  
  2525.  
  2526.  
  2527.  
  2528.  
  2529.  
  2530.  
  2531. 6.2. Darstellung von Funktionen und Vorschriften                            37
  2532.  
  2533.  
  2534. beim Umsetzen der Anweisungen der einzelnen Vorschriften erforderlich ist, ist
  2535. diese bei der Verwendung von C vorzuziehen.
  2536.  
  2537. 6.3.  Darstellung der Attribute
  2538.  
  2539. Die Klassen des aktuellen  Teilbaums  werden  als  Menge  dargestellt  und  in
  2540. Modula-2 als ARRAY OF BITSET realisiert. Zur Darstellung der einzelnen Klassen
  2541. werden diese durchnumeriert.  Die zulaessigen Vorschriften  werden  durch  ein
  2542. boolesches  Feld  realisiert.  Die kostenguenstigste Vorschrift jeder Funktion
  2543. wird durch den Wert einer Prozedur-Variablen und die zugehoerigen Kosten durch
  2544. einen INTEGER-Wert dargestellt.
  2545.  
  2546. Mit Ausnahme der zulaessigen Vorschriften  werden  alle  Attribute  im  Knoten
  2547. abgespeichert.  Bei  den zulaessigen Vorschriften ist dies nicht notwendig, da
  2548. diese nur solange benoetigt werden, bis  die  kostenguenstigsten  Vorschriften
  2549. feststehen.  Lokale Variablen der Prozedur yyTraverse wuerden deshalb zu Real-
  2550. isierung vollkommen ausreichen.
  2551.  
  2552. Da aber auszerdem der Zeitraum von Berechnung bis Auswertung  der  zulaessigen
  2553. Vorschriften  fuer verschiedene Knoten voellig disjunkt ist, genuegt sogar ein
  2554. einziges globales Feld zur Darstellung.
  2555.  
  2556. 6.4.  Speicherverwaltung
  2557.  
  2558. Da Groesze und Struktur der Daten, die  zur  Vorbereitung  der  Transformation
  2559. benoetigt  werden, bei der Implementierung des Baumes i.a. nicht bekannt sind,
  2560. wird im Baum lediglich Platz  fuer  eine  Adresse  reserviert.  Bei  der  Vor-
  2561. bereitung  der Transformation wird dann fuer jeden Knoten dynamischer Speicher
  2562. beschafft, um die Attribute abzuspeichern.  Der  Zeiger  auf  den  dynamischen
  2563. Speicher  wird  im  Knoten abgelegt, sodasz ueber die Knoten jederzeit auf die
  2564. Attribute zugegriffen werden kann.
  2565.  
  2566. Da diese Attribute nach Durchfuehrung der Transformation nicht mehr  benoetigt
  2567. werden,  sollte  der  belegte  Speicher  wieder  freigegeben  werden.  Um dies
  2568. effizient durchzufuehren, enthaelt der generierte  Transformator  eine  eigene
  2569. Speicherverwaltung,  die  nach dem Haldenprinzip arbeitet. Die Speicherverwal-
  2570. tung beschafft den Speicher in groeszeren Einheiten vom System und vergibt ihn
  2571. im  benoetigten Umfang. Nach der Transformation wird der Speicher schlieszlich
  2572. in den groszen Einheiten, die bereits bei  der  Beschaffung  linear  verkettet
  2573. wurden, wieder freigegeben.
  2574.  
  2575. Durch diese Methode wird zweierlei erreicht.  Zum  einen  kann  die  Speicher-
  2576. freigabe  sehr  schnell  durchgefuehrt  werden,  da kein aufwendiger Durchlauf
  2577. durch den Baum notwendig ist, wie er entstuende, wenn der  vergebene  Speicher
  2578. nur  ueber  die  Knoten zu erreichen waere. Auszerdem wird vermieden, dasz der
  2579. Speicher durch die Verwendung in kleine, kaum wiederverwendbare  Stuecke  zer-
  2580. faellt.
  2581.  
  2582. 6.5.  Berechnung der Klassen
  2583.  
  2584. Grundlage zur Berechnung der Klassen des aktuellen Teilbaums sind die  Knoten-
  2585. beschreibungen. Da die Berechnung abhaengig vom aktuellen Knoten durchgefuehrt
  2586. wird, genuegt es hierbei, die  Knotenbeschreibungen  zu  betrachten,  die  zum
  2587.  
  2588.  
  2589.  
  2590.  
  2591.  
  2592.  
  2593.  
  2594.  
  2595.  
  2596.  
  2597. 38                         6. Implementierung von Transformationen durch ESTRA
  2598.  
  2599.  
  2600. aktuellen Knoten passen.
  2601.  
  2602. Falls alle Soehne eines Knotens zu den  jeweiligen  Klassen  aus  der  Knoten-
  2603. beschreibung  passen,  paszt  auch  der  aktuelle  Teilbaum  zu dieser Knoten-
  2604. beschreibung. Folglich  paszt  auch  die  Klasse  auf  der  linken  Seite  der
  2605. zugehoerigen Knotenproduktion.
  2606.  
  2607. Da mit einer Klasse immer auch deren Oberklasse auf einen Teilbaum paszt, wird
  2608. hier  nicht  nur diese Klasse, sondern auch deren transitive Huelle bezueglich
  2609. der Oberklassenrelation erkannt.
  2610.  
  2611. Da die Hauptbeschreibung eines Knotens immer auf diesen  Knoten  passen  musz,
  2612. wird  deren  transitive  Huelle  immer in die Klassen des aktuellen Teilbaumes
  2613. aufgenommen. Beim Erkennen einer Knotenbeschreibung koennen diese deshalb ver-
  2614. nachlaessigt werden, da sie ja ohnehin erkannt werden.
  2615.  
  2616. 6.6.  Berechnung der zulaessigen Vorschriften
  2617.  
  2618. Um  die  zulaessigen  Vorschriften  festzulegen,   werden   die   Muster   der
  2619. Vorschriften,  mit dem Teilbaum verglichen. Zu diesem Zweck werden alle Muster
  2620. betrachtet, die mit dem aktuellen Knoten vertraeglich sind.  Es werden als nur
  2621. solche  Muster  untersucht,  die mit dem aktuellen Knoten beginnen, oder einer
  2622. Klasse darstellen, aus der der aktuelle Knoten ableitbar ist.
  2623.  
  2624. Um festzustellen, ob ein Muster mit  dem  aktuellen  Teilbaum  uebereinstimmt,
  2625. wird  jeder  Knoten und jede Klasse des Muster mit dem aktuellen Teilbaum ver-
  2626. glichen. Falls es sich bei der Wurzel eines Musters um einen  Knoten  handelt,
  2627. musz  dieser nicht ueberprueft werden, da seine Uebereinstimmung bereits durch
  2628. die Auswahl der Muster gegeben ist. Ebenso ist es nicht erforderlich,  Klassen
  2629. im  Muster zu ueberpruefen, die bei einer Normierung des Musters entfallen, da
  2630. diese immer vorliegen, wenn der Baum der gegebenen Grammatik genuegt.
  2631.  
  2632. Bei Uebereinstimmung des Musters mit dem Teilbaum und Zutreffen der  eventuell
  2633. vorhandenen Bedingung wird die Vorschrift festgehalten.
  2634.  
  2635. 6.7.  Berechnung der kostenguenstigsten Vorschriften
  2636.  
  2637. Zur Festlegung der  kostenguenstigsten  Vorschrift  werden  die  Kosten  aller
  2638. anwendbaren  Vorschriften bestimmt. Ergeben sich dabei fuer eine Funktion ger-
  2639. ingere Kosten als sie zuvor vorlagen,  werden  die  betreffende  Funktion  und
  2640. diese Kosten festgehalten. Da die Kosten einer Vorschrift von den Kosten einer
  2641. Funktion fuer den selben Knoten abhaengen  koennen,  genuegt  es  i.a.  jedoch
  2642. nicht,  fuer  jede  Vorschrift  einmal die Kosten zu berechnen. Die einfachste
  2643. Vorgehensweise besteht darin, die Berechnung der Kosten fuer alle Vorschriften
  2644. solange zu wiederholen, bis sich keine Verbesserungen der Kosten mehr ergeben.
  2645. Da dieses Verfahren zu sehr vielen unnoetigen Berechnungen fuehren musz,  wird
  2646. eine  Optimierung  durchgefuehrt,  die  in den meisten praktischen Faellen mit
  2647. einem Durchlauf auskommt.
  2648.  
  2649. Offensichtlich ist eine Wiederholung der Berechnung, wenn ueberhaupt dann  nur
  2650. fuer  solche  Vorschriften  erforderlich,  deren  Kosten  von den Kosten einer
  2651. anderen Funktion fuer den aktuellen Knoten abhaengen.  Die Vorschriften werden
  2652. deshalb  gemaesz  diesem Kriterium in zwei Gruppen gegliedert. Die eine Gruppe
  2653.  
  2654.  
  2655.  
  2656.  
  2657.  
  2658.  
  2659.  
  2660.  
  2661.  
  2662.  
  2663. 6.7. Berechnung der kostenguenstigsten Vorschriften                         39
  2664.  
  2665.  
  2666. (und die umfaszt in der Praxis alle oder zumindest die  meisten  Vorschriften)
  2667. musz  nur einmal abgearbeitet werden. Die uebrigen Vorschriften werden (sofern
  2668. mindestens zwei  verbleiben)  wiederholt  abgearbeitet,  bis  sich  bei  einem
  2669. Durchlauf keine Verbesserung ergibt.
  2670.  
  2671.  
  2672.  
  2673.  
  2674.  
  2675.  
  2676.  
  2677.  
  2678.  
  2679.  
  2680.  
  2681.  
  2682.  
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698.  
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.                                       40
  2729.  
  2730.  
  2731. 7.  Bottom-Up Pattern-Matching mit einem Baumautomaten
  2732.  
  2733. Bei dem in Kapitel 6 vorgestellten Verfahren zum Festlegen der auf einen Teil-
  2734. baum  anwendbaren  Vorschriften wird jedes Muster getrennt betrachtet. Das hat
  2735. zur Folge, dasz der Aufwand fuer diesen Schritt mit Zahl und  Groesze  der  zu
  2736. untersuchenden  Muster  zunimmt.   Beim sogenannten Bottom-Up Pattern-Matching
  2737. mit einem Baumautomaten [HoO82] wird dies vermieden.
  2738.  
  2739. Bei diesem Verfahren werden zum Zeitpunkt  der  Generierung  alle  Mengen  von
  2740. Mustern  bestimmt,  die  fuer  das Pattern-Matching von Bedeutung sind.  Diese
  2741. Mengen bilden den Zustandsraum des Baumautomaten. Das Pattern-Matching erfolgt
  2742. dann,  indem  fuer jeden Knoten des Baumes der Zustand berechnet wird, der die
  2743. Menge von Mustern darstellt, welche auf den zugehoerigen Teilbaum passen.  Aus
  2744. diesem  Zustand  laeszt sich unmittelbar ablesen, welche Vorschriften aufgrund
  2745. ihrer Muster  in  Frage  kommen.   Eventuell  vorhandene  Bedingungen  muessen
  2746. weiterhin gesondert ueberprueft werden.
  2747.  
  2748. 7.1.  Relevante Muster
  2749.  
  2750. Bevor der Zustandsraum bestimmt werden kann, muessen  die  relevanten  Muster,
  2751. d.h.  die  Muster, die fuer das Bottom-Up Pattern-Matching von Bedeutung sind,
  2752. festgelegt werden. Grundlage fuer die Bestimmung der  relevanten  Muster  sind
  2753. die normierten Muster der gegebenen Vorschriften.
  2754.  
  2755. Fuer eine gegebene Menge P<N> normierter Muster ist die Menge relevanter  Mus-
  2756. ter die kleinste Menge P<R> mit den Eigenschaften:
  2757.  
  2758. 1.   P<N>  P<R>
  2759.      Die vorgegeben normierten Muster sind relevant.
  2760.  
  2761. 2.   n (p<1>, ..., p<m>)  P<R>
  2762.       p<1>   P<R>, ..., p<m>   P<R>
  2763.      Wenn ein Muster relevant ist, sind auch alle seine Teilmuster relevant.
  2764.  
  2765. 3.   c  P<R>, c -> n (p<1>, ..., p<m>)
  2766.       Normalize (n (p<1>, ..., p<m>))  P<R>
  2767.      Ist ein einer Klasse entsprechendes Muster relevant, dann ist auch  jedes
  2768.      normierte  Muster  einer aus dieser Klasse ableitbaren Knotenbeschreibung
  2769.      relevant.
  2770.  
  2771. Durch  (1)  wird  sichergestellt,  dasz  die  vorgegebenen  Muster,  die  beim
  2772. Pattern-Matching  erkannt werden sollen, in der Menge P<R> enthalten sind. Mit
  2773. (2) wird dafuer gesorgt, dasz auch die Teilmuster, die zum Erkennen eines Mus-
  2774. ters  beitragen,  in P<R> enthalten sind.  Da die Klassen zwar in den Mustern,
  2775. nicht aber im realen Baum  vorkommen,  muessen  die  normierten  Muster  aller
  2776. Knotenbeschreibungen,  die einer in P<R> enthaltenen Klasse entsprechen, eben-
  2777. falls in P<R> liegen (3), damit die Klassen anhand dieser Muster erkannt  wer-
  2778. den koennen.
  2779.  
  2780. Abb. 7.1 zeigt die relevanten Muster, die entstehen, wenn wir die Mustern  '+'
  2781. (const, const) und '+' (expr, expr) zugrunde legen.
  2782.  
  2783.  
  2784.  
  2785.  
  2786.  
  2787.  
  2788.  
  2789.  
  2790.  
  2791.  
  2792.  
  2793. 7.1. Relevante Muster                                                       41
  2794.  
  2795.  
  2796.  
  2797.     ______________________________________________________________________
  2798.  
  2799.     P<N> = { p<0>, p<1> }
  2800.     P<R> = { p<0>, p<1>, p<2>, p<3> }
  2801.  
  2802.     mit:
  2803.     p<0> =      '+'         (const, const)
  2804.     p<1> =      '+'         (:, :)Normierung von '+' (expr, expr)
  2805.     p<2> =      const       Teilmuster von p<0>
  2806.     p<3> =      Const       ()Beschreibung eines Knotens der Klasse const
  2807.     ______________________________________________________________________
  2808.  
  2809.     Abb. 7.1: relevante Muster
  2810.  
  2811.  
  2812.  
  2813. 7.2.  Zustaende
  2814.  
  2815. Zur Beschreibung der Zustaende Q  des  Baumautomaten  koennte  die  Menge  2PR
  2816. verwendet  werden.  Tatsaechlich koennen jedoch nicht alle Teilmengen von P<R>
  2817. als Zustaende vorkommen, da  alle  Zustaende  notwendigerweise  die  folgenden
  2818. Bedingungen erfuellen muessen.
  2819.  
  2820. 1.   p<1>, p<2>  q  _ p<1>||p<2>
  2821.  
  2822. 2.   p<1>  P<R>, p<2>  q, p<1><p<2>
  2823.       p<1>  q
  2824.  
  2825. Die Bedingungen resultieren  daraus,  das  jeder  Zustand  einen  realen  Baum
  2826. beschreiben  musz.  Es  ist deshalb nicht moeglich, dasz ein Zustand zwei sich
  2827. widersprechende Muster enthaelt (1). Auszerdem musz mit dem groeszeren  Muster
  2828. p<2> immer auch das kleinere Muster p<1> in q liegen.
  2829.  
  2830. In unserem Beispiel erfuellen nur sechs  der  16  Mengen  diese  Eigenschaften
  2831. (Abb. 7.2). Die uebrigen scheiden aus (Abb. 7.3).
  2832.  
  2833.  
  2834.     ______________________________________________________________________
  2835.  
  2836.     Q = { q<0>, q<1>, q<2>, q<3>, q<4>, q<5> }
  2837.  
  2838.     mit:
  2839.     q<0> =      { p<0>, p<1>, p<2> }
  2840.     q<1> =      { p<1>, p<2> }
  2841.     q<2> =      { p<1> }
  2842.     q<3> =      { p<2>, p<3> }
  2843.     q<4> =      { p<2> }
  2844.     q<5> =      { }
  2845.     ______________________________________________________________________
  2846.  
  2847.     Abb. 7.2: Zustaende des Baumautomaten
  2848.  
  2849.  
  2850. Dasz die angegebenen Bedingungen nicht hinreichend sind, zeigt sich an unserem
  2851. Beispiel. Auf Grund der Grammatik (Abb. 7.1.) musz immer, wenn die Muster p<1>
  2852.  
  2853.  
  2854.  
  2855.  
  2856.  
  2857.  
  2858.  
  2859.  
  2860.  
  2861.  
  2862. 42                       7. Bottom-Up Pattern-Matching mit einem Baumautomaten
  2863.  
  2864.  
  2865. und p<2> passen, auch p<0> passen. Damit scheidet der Zustand  q<1>,  der  nur
  2866. aus p<1> und p<2> besteht, aus. Der Zustand q<4> kann ebenfalls nie auftreten,
  2867. da p<2> nur passen kann, wenn auch p<1> oder p<3> paszt.
  2868.  
  2869.  
  2870.     ______________________________________________________________________
  2871.  
  2872.     { p<0>, p<1>, p<2>, p<3> }nicht relevant da: p<0> || p<3>
  2873.     { p<0>, p<1>, p<3> }nicht relevant da: p<0> || p<3>
  2874.     { p<0>, p<1> }  nicht relevant da: p<2> < p<0>
  2875.     { p<0>, p<2>, p<3> }nicht relevant da: p<0> || p<3>
  2876.     { p<0>, p<2> }  nicht relevant da: p<1> < p<0>
  2877.     { p<0>, p<3> }  nicht relevant da: p<2> < p<0>
  2878.     { p<0> }        nicht relevant da: p<1> < p<0>
  2879.     { p<1>, p<2>, p<3> }nicht relevant da: p<1> || p<3>
  2880.     { p<1>, p<3> }  nicht relevant da: p<1> || p<3>
  2881.     { p<3> }        nicht relevant da: p<1> < p<3>
  2882.     ______________________________________________________________________
  2883.  
  2884.     Abb. 7.3: nicht relevante Mengen von Mustern
  2885.  
  2886.  
  2887. Ein Ansatz zur Beseitigung dieses Mangel wird in Kapitel 7.7 gegeben.
  2888.  
  2889. In der Hauptbeschreibung eines Knotens ist fuer jeden Sohn eine  Klasse  fest-
  2890. gelegt.  Fuer  jeden  Sohn  sind  deshalb  nur  die  Zustaende  relevant,  die
  2891. ausschlieszlich Muster enthalten, die  aus  dieser  Klasse  abgeleitet  werden
  2892. koennen.
  2893.  
  2894. Jeder Klasse c wird deshalb die Menge der fuer diese Klasse relevanten  Muster
  2895. P<c> und der fuer diese Klasse relevante Zustaende Q<c> zugeordnet.
  2896.  
  2897.      P<c> := { p  P<R>  p < c  p = c }
  2898.      Q<c> := { q  Q  q  P<c> }
  2899.  
  2900. Ebenso wie den Klassen kann man auch jedem Knoten n die Menge der fuer  diesen
  2901. Knoten  relevanten Muster P<n> und die fuer diesen Knoten relevanten Zustaende
  2902. Q<n> zuordnen.
  2903.  
  2904.      P<n> := { p  P<R>  p < n  p = n }
  2905.      Q<n> := { q  Q  q  P<n> }
  2906.  
  2907. 7.3.  Zustandsuebergangsfunktionen
  2908.  
  2909. Um das Bottom-Up Pattern-Matching durchzufuehren, wird  fuer  jeden  Knoten  n
  2910. eine  Zustandsuebergangsfunktion  f<n>  benoetigt.   Die  Stelligkeit von f<n>
  2911. entspricht der Wertigkeit m des Knotens n.
  2912.  
  2913.      f<n>: Qc1 x ... x Qcm  Q<n>
  2914.  
  2915. Die Funktion f<n> bestimmt aufgrund der Zustaende q<1>, ..., q<m>  der  Soehne
  2916. eines Knotens n den Zustand fuer diesen Knoten.
  2917.  
  2918.  
  2919.  
  2920.  
  2921.  
  2922.  
  2923.  
  2924.  
  2925.  
  2926.  
  2927.  
  2928.  
  2929. 7.3. Zustandsuebergangsfunktionen                                           43
  2930.  
  2931.  
  2932. Um fuer gegebene Zustaende q<1>, ..., q<m>, q = f<n> (q<1>, ..., q<m>) festzu-
  2933. legen,  wird  so  vorgegangen, dasz fuer alle Muster p  P<n> geprueft wird, ob
  2934. sie in q enthalten sein muessen.
  2935.  
  2936. 1.   n (p<1>, ..., p<m>)  P<n>, p<1>  q<1>, ..., p<m>  q<m>
  2937.       n (p<1>, ..., p<m>)  q
  2938.  
  2939. 2.   c -> n (c<1>, ..., c<m>), Normalize (n (c<1>, ..., c<m>))  q  c  q
  2940.  
  2941. 3.   c -> n (c<1>, ..., c<m>), Normalize (n (c<1>, ..., c<m>)) = c c  q
  2942.  
  2943. Ein Muster das mit einem Knoten beginnt liegt in q, wenn alle Teilmuster  p<i>
  2944. bereits  im  entsprechenden  Zustand q<i> liegen (1).  Das Muster einer Klasse
  2945. liegt in q falls, eine Knotenbeschreibung dieser  Klasse  in  normierter  Form
  2946. bereits  in  q  enthalten  ist  (2),  oder diese normierte Form mit der Klasse
  2947. uebereinstimmt (3).
  2948.  
  2949. Fuer unser Beispiel ergeben sich damit folgenden Uebergangsfunktionen.
  2950.  
  2951.  
  2952.     ______________________________________________________________________
  2953.  
  2954.  
  2955.     f<'+'> (q<0>, q<0>) = q<0>   f<'+'> (q<0>, q<1>) = q<0>   f<'+'> (q<0>, q<2>) = q<2>
  2956.     f<'+'> (q<0>, q<3>) = q<0>   f<'+'> (q<0>, q<4>) = q<0>   f<'+'> (q<0>, q<5>) = q<2>
  2957.     f<'+'> (q<1>, q<0>) = q<0>   f<'+'> (q<1>, q<1>) = q<0>   f<'+'> (q<1>, q<2>) = q<2>
  2958.     f<'+'> (q<1>, q<3>) = q<0>   f<'+'> (q<1>, q<4>) = q<0>   f<'+'> (q<1>, q<5>) = q<2>
  2959.     f<'+'> (q<2>, q<0>) = q<2>   f<'+'> (q<2>, q<1>) = q<2>   f<'+'> (q<2>, q<2>) = q<2>
  2960.     f<'+'> (q<2>, q<3>) = q<2>   f<'+'> (q<2>, q<4>) = q<2>   f<'+'> (q<2>, q<5>) = q<2>
  2961.     f<'+'> (q<3>, q<0>) = q<0>   f<'+'> (q<3>, q<1>) = q<0>   f<'+'> (q<3>, q<2>) = q<2>
  2962.     f<'+'> (q<3>, q<3>) = q<0>   f<'+'> (q<3>, q<4>) = q<0>   f<'+'> (q<3>, q<5>) = q<2>
  2963.     f<'+'> (q<4>, q<0>) = q<0>   f<'+'> (q<4>, q<1>) = q<0>   f<'+'> (q<4>, q<2>) = q<2>
  2964.     f<'+'> (q<4>, q<3>) = q<0>   f<'+'> (q<4>, q<4>) = q<0>   f<'+'> (q<4>, q<5>) = q<2>
  2965.     f<'+'> (q<5>, q<0>) = q<2>   f<'+'> (q<5>, q<1>) = q<2>   f<'+'> (q<5>, q<2>) = q<2>
  2966.     f<'+'> (q<5>, q<3>) = q<2>   f<'+'> (q<5>, q<4>) = q<2>   f<'+'> (q<5>, q<5>) = q<2>
  2967.  
  2968.     f<Const> () = q<3> f<Ident> () = q<5>
  2969.     __________________________________________________________________________
  2970.  
  2971.     Abb. 7.4: Zustandsuebergangsfunktionen
  2972.  
  2973.  
  2974.  
  2975. Das Pattern-Matching laeuft nun so ab, dasz in einem Bottom-Up-Durchlauf durch
  2976. den  Baum  fuer  jeden  Knoten ein Zustand qQ berechnet wird. Diese Berechnung
  2977. erfolgt, indem die zum jeweiligen Knoten n gehoerige  Funktion  f<n>  auf  die
  2978. bereits berechneten Zustaende q<1>, ..., q<m> der Soehne angewandt wird.
  2979.  
  2980. 7.4.  Felder zur Darstellung der Zustandsuebergangsfunktionen
  2981.  
  2982. Um die  Zustandsuebergangsfunktionen  darzustellen,  koennte  man  fuer  jeden
  2983. Knoten  ein Feld vorsehen. Die Felder haetten jeweils soviele Dimensionen, wie
  2984. der zugehoerige Knoten Soehne hat. Die Eintraege der Felder koennen zum  Zeit-
  2985. punkt  der  Generierung  bestimmt  werden.   Zur  Laufzeit waere lediglich ein
  2986.  
  2987.  
  2988.  
  2989.  
  2990.  
  2991.  
  2992.  
  2993.  
  2994.  
  2995.  
  2996. 44                       7. Bottom-Up Pattern-Matching mit einem Baumautomaten
  2997.  
  2998.  
  2999. Zugriff auf das Feld erforderlich, um den Zustand fuer den aktuellen Knoten zu
  3000. bestimmen.
  3001.  
  3002.  
  3003.     ______________________________________________________________________
  3004.  
  3005.     '+'     (i, j)
  3006.  
  3007.     _________________________________________________
  3008.      i \ j   q<0>   q<1>   q<2>   q<3>   q<4>   q<5>
  3009.     _________________________________________________
  3010.       q<0>   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3011.       q<1>   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3012.       q<2>   q<2>   q<2>   q<2>   q<2>   q<2>   q<2>
  3013.       q<3>   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3014.       q<4>   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3015.       q<5>   q<2>   q<2>   q<2>   q<2>   q<2>   q<2>
  3016.     _________________________________________________
  3017.    
  3018.  
  3019.  
  3020.  
  3021.  
  3022.  
  3023.  
  3024.           
  3025.  
  3026.  
  3027.  
  3028.  
  3029.  
  3030.  
  3031.                                                     
  3032.  
  3033.  
  3034.  
  3035.  
  3036.  
  3037.  
  3038.  
  3039.  
  3040.  
  3041.     Const   ()
  3042.  
  3043.     ______
  3044.      q<3>
  3045.     ______
  3046.    |
  3047.          |
  3048.  
  3049.  
  3050.     Ident   ()
  3051.  
  3052.     ______
  3053.      q<5>
  3054.     ______
  3055.    |
  3056.          |
  3057.  
  3058.     __________________________________________________________________________
  3059.  
  3060.     Abb. 7.5: Felder zur Darstellung der Zustandsuebergangsfunktionen
  3061.  
  3062.  
  3063. Abb. 7.5 zeigt die Felder zur  Darstellung  der  Zustandsuebergangsfunktionen,
  3064. die sich fuer unser Beispiel ergeben.
  3065.  
  3066. Da fuer Soehne aus der Klasse c nur  Zustaende  aus  Q<c>  vorkommen  koennen,
  3067. wuerde  es ausreichen die Felder fuer diesen Teil zu realisieren. Da aber Mus-
  3068. ter und damit auch Zustaende durchaus fuer verschiedene Klassen relevant  sein
  3069. koennen,  kann  die  Codierung  dieser Zustaende nicht immer dicht liegen. Bei
  3070. realistischen Beispielen waeren die Felder deshalb  sehr  grosz  jedoch  nicht
  3071. vollstaendig besetzt.
  3072.  
  3073. Um den enormen Speicherbedarf fuer die mehrdimensionalen Felder zu  vermeiden,
  3074. liegt es nahe, eine Komprimierung durchzufuehren.
  3075.  
  3076. 7.5.  Automaten zur Darstellung der Uebergangsfunktionen
  3077.  
  3078. Die Komprimierung erfolgt in Anlehnung an das  in  [BMW87]  vorgestellte  Ver-
  3079. fahren.   Im  ersten  Schritt werden an Stelle der Felder Automaten aufgebaut.
  3080. Diese Automaten arbeiten horizontal, die Soehne eines Knotens  werden  hierbei
  3081. von  links  nach  rechts abgearbeitet, wobei jeweils ein durch den Zustand des
  3082. Sohnes gesteuerter Uebergang im Automat stattfindet. Anstelle des Zugriffs auf
  3083.  
  3084.  
  3085.  
  3086.  
  3087.  
  3088.  
  3089.  
  3090.  
  3091.  
  3092.  
  3093. 7.5. Automaten zur Darstellung der Uebergangsfunktionen                     45
  3094.  
  3095.  
  3096. ein n-dimensionales Feld erfolgen also n Uebergaenge in einem Automaten.
  3097.  
  3098.  
  3099.     ______________________________________________________________________
  3100.  
  3101.     ______________________________________________________________________
  3102.  
  3103.     Abb. 7.6: Automaten zur Darstellung der Zustandsuebergangsfunktionen
  3104.  
  3105.  
  3106. In Abb. 7.6 sind die Automaten dargestellt,  die  den  Feldern  von  Abb.  7.5
  3107. entsprechen.  Die  durch  Kreise  dargestellten Zustaende werden bei der Abar-
  3108. beitung der  Soehne  eines  Knotens  durchlaufen.   Die  durch  Quadrate  dar-
  3109. gestellten  Endzustaende,  stellen das Ergebnis der Zustandsuebergangsfunktion
  3110. dar.
  3111.  
  3112. Es ist unschwer zu erkennen, dasz die Automaten zum  Teil  vereinfacht  werden
  3113. kann.  Offensichtlich  sind  die  Zustaende S2, S3, S5 und S6 aequivalent. Das
  3114. selbe gilt fuer S4 und S7. Faszt man diese Zustaende zusammen so  erhaelt  man
  3115. einen reduzierten Automaten (Abb. 7.7).
  3116.  
  3117.  
  3118.     ______________________________________________________________________
  3119.  
  3120.     ______________________________________________________________________
  3121.  
  3122.     Abb. 7.7: reduzierte Automaten zur Berechnung der Zustaende
  3123.  
  3124.  
  3125. Um diese Komprimierung zu erreichen, wird so vorgegangen,  dasz  man  vertrae-
  3126. gliche  Zustaende  zusammenfaszt, wobei Zustaende dann vertraeglich sind, wenn
  3127. sie bei der gleichen Eingabe zum selben Zustand fuehren. Da sich die Zusammen-
  3128. fassung  von  Zustaenden  im  allgemeinen positiv auf die Vertraeglichkeit der
  3129. Vorgaenger auswirkt, sollten dabei alle Nachfolger eines  Zustandes  auf  moe-
  3130. gliche  Vertraeglichkeiten  untersucht  und  moegliche  Zusammenfassungen dur-
  3131. chgefuehrt sein, bevor der Zustand selbst betrachtet wird.
  3132.  
  3133. 7.6.  Realisierung der Automaten
  3134.  
  3135. Um den Automaten zu realisieren, werden die zu einem Zustand gehoerigen Ueber-
  3136. gaenge als eindimensionale Felder dargestellt (Abb. 7.8).
  3137.  
  3138.  
  3139.  
  3140.  
  3141.  
  3142.  
  3143.  
  3144.  
  3145.  
  3146.  
  3147.  
  3148.  
  3149.  
  3150.  
  3151.  
  3152.  
  3153.  
  3154.  
  3155.  
  3156.  
  3157.  
  3158.  
  3159.  
  3160.  
  3161. 46                       7. Bottom-Up Pattern-Matching mit einem Baumautomaten
  3162.  
  3163.  
  3164.  
  3165.     ______________________________________________________________________
  3166.  
  3167.  
  3168.     ______________________________________________
  3169.           q<0>   q<1>   q<2>   q<3>   q<4>   q<5>
  3170.     ______________________________________________
  3171.      S1   S2     S2     S3     S2     S2     S3
  3172.     ______________________________________________
  3173.    
  3174.  
  3175.        
  3176.  
  3177.                                                  
  3178.  
  3179.  
  3180.  
  3181.  
  3182.     ______________________________________________
  3183.           q<0>   q<1>   q<2>   q<3>   q<4>   q<5>
  3184.     ______________________________________________
  3185.      S2   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3186.     ______________________________________________
  3187.    
  3188.  
  3189.        
  3190.  
  3191.                                                  
  3192.  
  3193.  
  3194.  
  3195.  
  3196.     ______________________________________________
  3197.           q<0>   q<1>   q<2>   q<3>   q<4>   q<5>
  3198.     ______________________________________________
  3199.      S3   q<2>   q<2>   q<2>   q<2>   q<2>   q<2>
  3200.     ______________________________________________
  3201.    
  3202.  
  3203.        
  3204.  
  3205.                                                  
  3206.  
  3207.  
  3208.  
  3209.     __________________________________________________________________________
  3210.  
  3211.     Abb. 7.8: Felder zur Berechnung der Zustandsuebergaenge
  3212.  
  3213.  
  3214. Um den Speicherbedarf fuer diese Felder zu  reduzieren,  werden  alle  in  ein
  3215. gemeinsames  Feld  eingebettet. Bei diesem unter dem Begriff Kammvektortechnik
  3216. bekannten Verfahren werden soweit moeglich identische Eintraege  verschiedener
  3217. Felder  ueberlagert,  und  Luecken  in  den Feldern durch die Eintraege andere
  3218. Felder gefuellt.
  3219.  
  3220.  
  3221.     ______________________________________________________________________
  3222.  
  3223.  
  3224.     __________________________________________________________________________________________________________
  3225.      S2   S2   S3   S2   S2   S3
  3226.                                    q<0>   q<0>   q<2>   q<0>   q<0>   q<2>
  3227.                                                                       q<2>   q<2>   q<2>   q<2>   q<2>   q<2>
  3228.     __________________________________________________________________________________________________________
  3229.    
  3230.  
  3231.                                                                                                              
  3232.  
  3233.  
  3234.  
  3235.  
  3236.     __________________________________________________________________________________________________________
  3237.      S2   S2   S3   S2   S2   S3   q<0>   q<0>   q<2>   q<0>   q<0>   q<2>   q<2>   q<2>   q<2>   q<2>   q<2>
  3238.     __________________________________________________________________________________________________________
  3239.    |
  3240.                                                                                                              |
  3241.  
  3242.     __________________________________________________________________________
  3243.  
  3244.     Abb. 7.8: Einbettung des Automaten in ein eindimensionales Feld
  3245.  
  3246.  
  3247. In unserem Beispiel (Abb. 7.9) ist die erzielte Einsparung sehr gering, da  es
  3248. keine  Luecken  gibt.  Dies  liegt  daran, dasz die zugrunde gelegte Grammatik
  3249. extrem einfach ist. Die Klasse (expr), die bei der Festlegung der  zulaessigen
  3250. Soehne  von  '+'  verwendet  wurde,  fuehrt zu keinerlei Einschraenkungen, und
  3251. somit sind alle Zustaende fuer die Soehne moeglich (Q<expr> = Q).
  3252.  
  3253.  
  3254.  
  3255.  
  3256.  
  3257.  
  3258.  
  3259.  
  3260.  
  3261.  
  3262.  
  3263.  
  3264. 7.6. Realisierung der Automaten                                             47
  3265.  
  3266.  
  3267. In realistischen Beispielen wird durch diese Masznahme jedoch eine  drastische
  3268. Einsparung   erzielt,   da  dort  durch  Verwendung  vieler  sich  gegenseitig
  3269. ausschlieszender Klassen in den einzelnen Felder viele Luecken entstehen,  die
  3270. bei der Einbettung in ein gemeinsames Feld zum Teil geschlossen werden.
  3271.  
  3272. 7.7.  Vermeidung unnoetiger Zustaende
  3273.  
  3274. In 9.2. wurde festgestellt, dasz die Bedingungen zur Festlegung der  Zustaende
  3275. des  Baumautomaten  nicht  hinreichend  sind,  um  sicher zu stellen, dasz nur
  3276. solche Zustaende betrachtet werden, die wirklich eintreten  koennen.  Es  gibt
  3277. jedoch eine Moeglichkeit, diesen Mangel im nachhinein zu beheben.
  3278.  
  3279. Offensichtlich ist es so, dasz  die  moeglichen  Zustaende  des  Baumautomaten
  3280. genau  den erreichbaren Endzustaenden der Automaten zur Darstellung der Ueber-
  3281. gangsfunktionen entsprechen.   Um  sie  zu  erkennen,  genuegt  es  also,  die
  3282. erreichbaren Zustaende dieser Automaten zu berechnen.
  3283.  
  3284. 7.8.  Implementierung des Bottom-Up Pattern-Matching
  3285.  
  3286. Neben dem eindimensionalen  Feld  (yyComb),  das  die  horizontalen  Automaten
  3287. beschreibt,  wird  fuer  die  Realisierung  des Pattern-Matching noch ein Feld
  3288. benoetigt, das jedem Zustand des Baumautomaten  die  Menge  der  Vorschriften,
  3289. deren Muster paszt, zuordnet (yySets).
  3290.  
  3291. Das Pattern-Matching laeuft dann fuer jeden Knoten c folgendermaszen ab:
  3292.  
  3293. 1.   state := const<c>
  3294.  
  3295. 2.    Soehne s<i> von c
  3296.      state := yyComb [state + yyTraverse (s<i>)]
  3297.  
  3298. 3.   match := ADR (yySets [state])
  3299.  
  3300. 4.   RETURN state
  3301.  
  3302. Zu Beginn (1) wird eine lokale Variable  state  mit  einem  knotenspezifischen
  3303. Wert  initialisiert.  Die  Variable  state beschreibt sowohl die Zustaende des
  3304. horizontalen Automaten als auch die des Baumautomaten. Im zweiten Schritt  (2)
  3305. werden  die Soehne rekursiv abgearbeitet. Gleichzeitig werden, gesteuert durch
  3306. die Zustaende der Soehne, die von yyTraverse als  Ergebnis  geliefert  werden,
  3307. die  Uebergaenge  im  horizontalen Automaten durchgefuehrt.  Schlieszlich wird
  3308. das  Ergebnis  fuer  den  eigenen  Teilbaum,  das  durch  die  Variable  state
  3309. beschrieben  wird, benutzt, um die Vorschriften zu bestimmen, deren Muster auf
  3310. den aktuellen Teilbaum passen (3) und anschlieszend zurueckgeliefert (4).
  3311.  
  3312. Wenn das Pattern-Matching  in  die  Prozedur  yyTraverse,  die  in  Kapitel  6
  3313. beschrieben ist, integriert wird, ergeben sich folgende Aenderungen.
  3314.  
  3315. 1.   Die Abarbeitung der Soehne wird  mit  der  Abarbeitung  des  horizontalen
  3316.      Automaten kombiniert (Punkte (1) und (2) von oben)
  3317.  
  3318. 2.   Die Berechnung der Klassen entfaellt, da diese  beim  Bottom-Up  Pattern-
  3319.      Matching nicht benoetigt werden.
  3320.  
  3321.  
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328.  
  3329.  
  3330. 48                       7. Bottom-Up Pattern-Matching mit einem Baumautomaten
  3331.  
  3332.  
  3333. 3.   Um die zulaessigen Vorschriften zu bestimmen, wird neben den  Bedingungen
  3334.      lediglich  die ueber die Variable match zugaengliche Menge benutzt (Punkt
  3335.      (3) von oben).
  3336.  
  3337. 4.   Die Prozedur yyTraverse liefert nun einen Zustand  als  Ergebnis  zurueck
  3338.      (Punkt (4) von oben).
  3339.  
  3340. Da Modula-2 keine initialisierte Variablen kennt, muessen auszerdem die Felder
  3341. yySets und yyComb eingelesen werden, bevor die Transformation vorbereitet wer-
  3342. den kann.
  3343.  
  3344. Die hier beschriebenen Unterschiede koennen im Anhang B.2, der beide Loesungen
  3345. im Vergleich zeigt, im Detail studiert werden.
  3346.  
  3347.  
  3348.  
  3349.  
  3350.  
  3351.  
  3352.  
  3353.  
  3354.  
  3355.  
  3356.  
  3357.  
  3358.  
  3359.  
  3360.  
  3361.  
  3362.  
  3363.  
  3364.  
  3365.  
  3366.  
  3367.  
  3368.  
  3369.  
  3370.  
  3371.  
  3372.  
  3373.  
  3374.  
  3375.  
  3376.  
  3377.  
  3378.  
  3379.  
  3380.  
  3381.  
  3382.  
  3383.  
  3384.  
  3385.  
  3386.  
  3387.  
  3388.  
  3389.  
  3390.  
  3391.  
  3392.  
  3393.  
  3394.  
  3395.                                       49
  3396.  
  3397.  
  3398. 8.  Vollstaendigkeit
  3399.  
  3400. Eine wesentliche Forderung, die an eine Spezifikation gestellt wird,  ist  die
  3401. der  Vollstaendigkeit. Eine Spezifikation heiszt vollstaendig, wenn sie geeig-
  3402. net ist, fuer jede zulaessige Eingabe die Transformation zu beschreiben.
  3403.  
  3404. Die allgemeine Frage,  ob  eine  Spezifikation  vollstaendig  ist,  ist  nicht
  3405. entscheidbar.  Im  folgenden  wird  deshalb eine schaerfere Eigenschaft betra-
  3406. chtet, die die Vollstaendigkeit  impliziert.  Obwohl  auch  diese  Eigenschaft
  3407. nicht  entscheidbar  ist,  hilft  sie uns einen Schritt weiter, denn einzelnen
  3408. Teile dieser Eigenschaft koennen entschieden werden und eignen sich, bestimmte
  3409. Luecken in der Vollstaendigkeit aufzuspueren.
  3410.  
  3411. Um eine Transformation durchzufuehren, wird die Aufgabe gestellt,  die  Wurzel
  3412. mit  der ersten Funktion der Spezifikation zu bearbeiten.  Um eine solche Auf-
  3413. gabe   zu   loesen,   musz   eine   passende   Vorschrift   gefunden   werden.
  3414. Funktionsaufrufe  in  den  Anweisungen dieser Vorschrift bilden neue Aufgaben,
  3415. die ebenfalls bearbeitet werden muessen.
  3416.  
  3417. Falls man sicherstellen kann, dasz zur Durchfuehrung  der  Transformation  nur
  3418. zulaessige Aufgaben gestellt werden (Einhaltung des Definitionsbereichs), dasz
  3419. fuer jede zulaessige Aufgabe eine passende Vorschrift existiert  (Ueberdeckung
  3420. des  Definitionsbereichs) und dasz alle zulaessigen Aufgaben abgearbeitet wer-
  3421. den koennen (Terminierung), dann ist die Spezifikation sicher vollstaendig.
  3422.  
  3423. 8.1.  Einhaltung des Definitionsbereichs
  3424.  
  3425. Um die Einhaltung des Definitionsbereichs sicherzustellen, musz geprueft  wer-
  3426. den, ob die Teilbaeume, auf die eine Funktion angewandt wird, in den durch den
  3427. Definitionsbereich festgelegten Klassen liegen.
  3428.  
  3429. Wenn beim Funktionsaufruf ein Selektor verwendet  wird,  wird  diese  Pruefung
  3430. vorgenommen,  indem  das  Teilmuster,  das  durch  den  Selektor bestimmt ist,
  3431. analysiert wird. Die Einhaltung des  Definitionsbereichs  ist  sichergestellt,
  3432. falls  dieses  Teilmuster  aus einer Klasse des Definitionsbereichs abgeleitet
  3433. werden kann.
  3434.  
  3435. Wird der zu transformierende Baum beim Funktionsaufruf auf eine  andere  Weise
  3436. festgelegt  (z.B.  durch  eine  Variable),  kann  die  Einhaltung  des Defini-
  3437. tionsbereichs nicht  automatisch  ueberprueft  werden,  da  dann  zur  Generi-
  3438. erungszeit keine Moeglichkeit besteht, die Klassenzugehoerigkeit dieses Baumes
  3439. zu bestimmen.  Der Anwender von ESTRAL wird in solchen Faellen durch eine War-
  3440. nung auf die Gefahr hingewiesen.
  3441.  
  3442. 8.2.  Ueberdeckung des Definitionsbereichs
  3443.  
  3444. Der wesentliche Bestandteil der Vollstaendigkeitspruefung ist die Pruefung, ob
  3445. der Definitionsbereich durch die Vorschriften abgedeckt wird.
  3446.  
  3447. Dieser Test wird durchgefuehrt, indem jede Klasse (c) des  Definitionsbereichs
  3448. (Domain) als (zunaechst einelementige) Menge von synthetisierten Mustern (syn)
  3449. aufgefaszt wird und alle realen Muster (real) ausgefiltert werden,  die  durch
  3450. eine Vorschrift abgedeckt werden. Die (in syn) verbliebenen Muster koennen mit
  3451.  
  3452.  
  3453.  
  3454.  
  3455.  
  3456.  
  3457.  
  3458.  
  3459.  
  3460.  
  3461. 50                                                         8. Vollstaendigkeit
  3462.  
  3463.  
  3464. den Vorschriften nicht bearbeitet werden, sie dokumentieren  die  Unvollstaen-
  3465. digkeit.
  3466.  
  3467. Um die Bedingungen der Vorschriften  zu  beruecksichtigen,  werden  zwei  Dur-
  3468. chlaeufe   unterschieden.   Im   ersten   Durchlauf  wird  versucht,  mit  den
  3469. Vorschriften auszukommen, die nicht mit einer Bedingung verknuepft sind. Falls
  3470. dies  nicht  gelingt,  werden  die  bedingten  Vorschriften ebenfalls zum Test
  3471. herangezogen. Schlieszlich wird fuer jedes  Muster,  das  zum  Schlusz  uebrig
  3472. geblieben  ist,  ein  Fehler  (Error)  gemeldet.  Muster die erst beim zweiten
  3473. Durchlauf ausgefiltert werden, fuehren zu einer Warnung (Warning).
  3474.  
  3475.  
  3476.     ______________________________________________________________________
  3477.  
  3478.     Cover
  3479.     for all functions f do
  3480.       for all c  Domain (f) do
  3481.         cp := MakePattern (c)
  3482.         syn := EmptyList
  3483.         Append (syn, cp)
  3484.         real := GetUnCondPatterns (f)
  3485.         match := EmptyList
  3486.         Filter (syn, real, match)
  3487.         real := GetCondPatterns (f)
  3488.         match := EmptyList
  3489.         Filter (syn, real, match)
  3490.         while _ IsEmpty (match) do
  3491.           p := TakeHead (match)
  3492.           Warning ('no unconditional pattern matching', p)
  3493.         while _ IsEmpty (syn) do
  3494.           p := TakeHead (syn)
  3495.           Error ('no pattern at all matching', p)
  3496.     ______________________________________________________________________
  3497.  
  3498.     Abb. 8.7: Ueberdeckung des Definitionsbereich
  3499.  
  3500.  
  3501. Zum Filtern (Abb. 8.8) wird die Funktion Relation von Abb.  7.6  herangezogen.
  3502. Wenn ein synthetisiertes Muster (sp) durch ein reales Muster (rp) vollstaendig
  3503. ueberdeckt wird, musz sp nicht weiter betrachtet werden. Ist rp  nicht  geeig-
  3504. net,  um  sp  vollstaendig zu ueberdecken, musz so vorgegangen werden, dasz sp
  3505. durch Anwenden der Produktionen der  Grammatik  durch  weitere  synthetisierte
  3506. Muster ersetzt wird (Extend), die das urspruengliche vollstaendig beschreiben.
  3507.  
  3508. Um diese Erweiterung des synthetisierten Musters (sp) zu  unterstuetzen,  wird
  3509. eine  Funktion RelationP benutzt. RelationP ist eine Erweiterung von Relation,
  3510. die fuer die Faelle unabhaengig  (independent)  und  groeszer  (greater)  eine
  3511. Position  zurueckliefert, an der eine sinnvolle Erweiterung ansetzen kann. Mit
  3512. Hilfe dieser Position und anhand  der  Grammatik  wird  dann  von  Extend  die
  3513. Erweiterung,  d.h.  die  Synthese  von  weiteren  Mustern  durchgefuehrt.  Die
  3514. entstandenen Muster werden in die Liste syn eingefuegt, um im folgenden  bear-
  3515. beitet zu werden.
  3516.  
  3517.  
  3518.  
  3519.  
  3520.  
  3521.  
  3522.  
  3523.  
  3524.  
  3525.  
  3526.  
  3527. 8.2. Ueberdeckung des Definitionsbereichs                                   51
  3528.  
  3529.  
  3530. Schlieszlich wird es moeglich sein, einige der generierten Muster auszufiltern
  3531. (match), andere Muster werden uebrig bleiben (rest).  Der Rest bildet den Aus-
  3532. gangspunkt fuer den naechsten Durchlauf.  Nach Betrachten aller realen  Muster
  3533. enthaelt  syn  alle  synthetisierten Muster, die nicht durch die realen Muster
  3534. ueberdeckt werden konnten.
  3535.  
  3536.  
  3537.     ______________________________________________________________________
  3538.  
  3539.     Filter (VAR syn, real, match: tPatternList)
  3540.     while _ Empty (syn) & _ Empty (real) do
  3541.       rest := EmptyList
  3542.       rp := TakeHead (real)
  3543.       while _ Empty (syn) do
  3544.         sp := TakeHead (syn)
  3545.         case RelationP (sp, rp, pos) of
  3546.         | equal, less:
  3547.             Append (match, sp)
  3548.         | inconsistent:
  3549.             Append (rest, sp)
  3550.         | independent, greater:
  3551.             if pos = undefined then
  3552.               Append (rest, sp)
  3553.             else
  3554.               Extend (sp, pos, syn)
  3555.       syn := rest
  3556.     ______________________________________________________________________
  3557.  
  3558.     Abb. 8.8: Filtern von Mustern
  3559.  
  3560.  
  3561. Abb. 8.9 zeigt zwei unabhaengige  Muster,  die  der  Grammatik  von  Abb.  4.1
  3562. entsprechen, fuer die RelationP jedoch keine sinnvolle Position zurueckliefern
  3563. kann (pos = undefined).
  3564.  
  3565.  
  3566.     ______________________________________________________________________
  3567.  
  3568.     sp = '+' (:,:)
  3569.     rp = const
  3570.     ______________________________________________________________________
  3571.  
  3572.     Abb. 8.9: Muster ohne sinnvolle Erweiterung
  3573.  
  3574.  
  3575. Fuer die beiden Muster sp und rp existiert keine sinnvolle  Erweiterung.  Zwar
  3576. wuerde  die  Belegung  der Blaetter von sp mit allen Moeglichkeiten, die durch
  3577. die Grammatik gegeben sind, dazu fuehren, dasz ein Teil der  dadurch  entstan-
  3578. denen  Muster  ausgefiltert  werden kann, doch wuerden dabei immer neue von rp
  3579. unabhaengige Muster entstehen, die weiterbearbeitet werden mueszten.   Um  die
  3580. Terminierung des Algorithmus an dieser Stelle sicherzustellen, wird in solchen
  3581. Faellen auf eine Erweiterung verzichtet. In pathologischen  Faellen  kann  das
  3582. zwar  dazu  fuehren,  dasz eine Eingabe irrtuemlich als unvollstaendig erkannt
  3583. wird, doch kommt dies in der Praxis kaum vor.
  3584.  
  3585.  
  3586.  
  3587.  
  3588.  
  3589.  
  3590.  
  3591.  
  3592.  
  3593.  
  3594.  
  3595. 52                                                         8. Vollstaendigkeit
  3596.  
  3597.  
  3598. 8.3.  Terminierung
  3599.  
  3600. Die Terminierung kann meist dadurch sichergestellt werden, dasz sich die Funk-
  3601. tionsaufrufe  auf  tieferliegende  Teilbaeume  beziehen.  Da  der  Eingabebaum
  3602. endlich ist, werden schlieszlich die  Blaetter  erreicht  und  folglich  keine
  3603. weiteren Funktionen aufgerufen.
  3604.  
  3605. Falls sich Funktionsaufrufe hingegen auf den aktuellen Teilbaum insgesamt bez-
  3606. iehen, wird die Terminierung in Frage gestellt. Denn durch einen solchen Funk-
  3607. tionsaufruf wird die Terminierung einer Vorschrift unmittelbar  von  der  Ter-
  3608. minierung der aufgerufenen Funktion abhaengig.  Damit entsteht eine Abhaengig-
  3609. keiten zwischen Funktionen (aufrufende und aufgerufene Funktion). Die  Abhaen-
  3610. gigkeit   beschraenkt   sich   allerdings  auf  das  Muster  der  betreffenden
  3611. Vorschrift. Auszerdem ist die Abhaengigkeit nur  dann  unvermeidbar,  wenn  es
  3612. keine  andere  Vorschrift  gibt,  die  alternativ angewandt werden koennte und
  3613. keine Abhaengigkeit hervorruft. Um unter solchen Bedingungen die  Terminierung
  3614. nachzuweisen,  mueszte  gezeigt  werden,  dasz  die  Entstehung von zyklischen
  3615. Abhaengigkeiten vermieden werden kann.
  3616.  
  3617. Falls diese Frage ueberhaupt  entscheidbar  ist,  ist  die  hierzu  notwendige
  3618. Untersuchung  auf  alle  Faelle  aeuszerst  aufwendig.   Andererseits sind die
  3619. Abhaengigkeiten zwischen Funktionen in der Praxis recht gering und somit  auch
  3620. von Hand zu ueberschauen. Von ESTRA wird deshalb zum Zeitpunkt der Generierung
  3621. kein Test auf Terminierung durchgefuehrt.
  3622.  
  3623.  
  3624.  
  3625.  
  3626.  
  3627.  
  3628.  
  3629.  
  3630.  
  3631.  
  3632.  
  3633.  
  3634.  
  3635.  
  3636.  
  3637.  
  3638.  
  3639.  
  3640.  
  3641.  
  3642.  
  3643.  
  3644.  
  3645.  
  3646.  
  3647.  
  3648.  
  3649.  
  3650.  
  3651.  
  3652.  
  3653.  
  3654.  
  3655.  
  3656.  
  3657.  
  3658.  
  3659.  
  3660.                                       53
  3661.  
  3662.  
  3663. 9.  Schnittstellen des Transformators
  3664.  
  3665. 9.1.  Struktur der Eingabebaeume
  3666.  
  3667. Bei der Entwicklung von ESTRA wurde eine Darstellung der attributierten Baeume
  3668. vorausgesetzt, wie sie von ast [Gro89] zur Verfuegung gestellt wird.
  3669.  
  3670.  
  3671.     ______________________________________________________________________
  3672.  
  3673.     CONST
  3674.        Plus= 1;
  3675.        Const= 2;
  3676.        Ident= 3;
  3677.        expr= 4;
  3678.        const= 5;
  3679.        index= 6;
  3680.  
  3681.     TYPE
  3682.        tTree= POINTER TO tNode;
  3683.        yexpr= RECORD pos: tPosition END;
  3684.        yconst= RECORD pos: tPosition END;
  3685.        yindex= RECORD pos: tPosition END;
  3686.        yPlus= RECORD pos: tPosition; lo: tTree; ro: tTree; END;
  3687.        yConst= RECORD pos: tPosition; value: INTEGER; END;
  3688.        yIdent= RECORD pos: tPosition; ident: tIdent; END;
  3689.        tNode= RECORD
  3690.          yyEstraInfo:ADDRESS;
  3691.          CASE Kind: INTEGER OF
  3692.          | expr:    expr:yexpr;
  3693.          | const:   const:yconst;
  3694.          | index:   index:yindex;
  3695.          | Plus:    Plus:yPlus;
  3696.          | Const:   Const:yConst;
  3697.          | Ident:   Ident:yIdent;
  3698.          END;
  3699.        END;
  3700.     ______________________________________________________________________
  3701.  
  3702.     Abb. 9.1: Darstellung der attributierten Baeume in Modula-2
  3703.  
  3704.  
  3705. Die attributierten Baeume werden als Zeiger auf variante Strukturen realisiert
  3706. (tTree).  Die  Struktur  (tNode)  enthaelt fuer jede Knotenart und jede Klasse
  3707. eine Variante. Die gueltige Variante wird durch das Tag-Feld (Kind) angezeigt.
  3708.  
  3709. Wuerde immer ueber die Variante, die durch das Tag-Feld ausgezeichnet ist, auf
  3710. den  Knoten  zugegriffen,  waeren  die Varianten, die den Klassen entsprechen,
  3711. ueberfluessig. Tatsaechlich ist es aber so, dasz diese Varianten benutzt  wer-
  3712. den,   um  auf  Attribute  von  Soehnen  zuzugreifen,  deren  Knotenart  nicht
  3713. feststeht. In unserem Beispiel kann auf diese Weise in jedem  Knoten  auf  das
  3714.  
  3715.  
  3716.  
  3717.  
  3718.  
  3719.  
  3720.  
  3721.  
  3722.  
  3723.  
  3724. 54                                        9. Schnittstellen des Transformators
  3725.  
  3726.  
  3727. Attribut  Pos zugegriffen werden. Damit dies wirklich funktioniert, genuegt es
  3728. nicht, dasz dieses Attribut in jeder Variante vorkommt, es musz auch immer  an
  3729. der selben Stelle stehen. Dies kann im allgemeinen sichergestellt werden, wenn
  3730. die Variante eines Knotens eine Erweiterungen der Varianten der  Klassen  dar-
  3731. stellen, aus denen er hervorgehen kann.
  3732.  
  3733. Das Feld yyEstraInfo dient zur Aufnahme der Attribute, die zur Festlegung  der
  3734. Transformation benoetigt werden.
  3735.  
  3736. 9.2.  Schnittstelle des generierten Moduls
  3737.  
  3738. Von ESTRA wird ein Modul generiert, das den  Namen  der  Transformation  (z.B.
  3739. Trans) erhaelt.
  3740.  
  3741.  
  3742.     ______________________________________________________________________
  3743.  
  3744.     DEFINITION MODULE Trans;
  3745.     IMPORT  Tree;
  3746.     TYPE    tTree = Tree.tTree
  3747.     (* for bottom-up pattern-matching only *)
  3748.     VAR     TransTabName: ARRAY [0..127] OF CHAR;
  3749.     PROCEDURE BeginTrans;
  3750.     PROCEDURE DoTrans (yyt: Tree.tTree);
  3751.     PROCEDURE CloseTrans;
  3752.     END Trans.
  3753.     ______________________________________________________________________
  3754.  
  3755.     Abb. 9.2: Schnittstelle des generierten Transformators
  3756.  
  3757.  
  3758. Die parameterlosen Prozeduren BeginTrans und CloseTrans  dienen  zur  Initial-
  3759. isierung  und  zur  Durchfuehrung  von  Abschluszarbeiten.  DoTrans fuehrt die
  3760. Transformation des Baumes yyt durch. Die Schnittstelle von DoTrans  entspricht
  3761. der  Schnittstelle  der ersten Funktion, die in Trans spezifiziert wurde. D.h.
  3762. falls diese Funktion vererbte oder  synthetisierte  Attribute  hat,  wird  die
  3763. Schnittstelle von DoTrans entsprechend erweitert.
  3764.  
  3765. Der Typ tTree, der zur Darstellung der Baeume verwendet wird, musz im  EXPORT-
  3766. Abschnitt  bekannt gemacht werden, damit er fuer die Prozedur DoTrans zur Ver-
  3767. fuegung steht.
  3768.  
  3769. Die Variable TransTabName wird bei Verwendung des  Bottom-Up  Pattern-Matching
  3770. Algorithmus  benutzt,  um  den  Namen  der  Tabellendatei  (hier  "Trans.tab")
  3771. aufzunehmen. Damit besteht die Moeglichkeit, den  Namen  vor  dem  Aufruf  von
  3772. BeginTrans zu umzusetzen, falls ein anderer Dateiname benutzt werden soll.
  3773.  
  3774.  
  3775.  
  3776.  
  3777.  
  3778.  
  3779.  
  3780.  
  3781.  
  3782.  
  3783.  
  3784.  
  3785.  
  3786.  
  3787.  
  3788.                                       55
  3789.  
  3790.  
  3791. 10.  Vergleich mit anderen Werkzeugen
  3792.  
  3793. 10.1.  Twig
  3794.  
  3795. Twig [AGT87]  ist  ein  Werkzeug  zur  Erstellung  von  Codegeneratoren.   Die
  3796. Beschreibung   der   Codegeneratoren  erfolgt  durch  Regeln,  die  aus  einer
  3797. Umschreibregel, Kosten und Aktionen, bestehen.
  3798.  
  3799. Eine Umschreibregel besteht aus einem  Muster  und  einem  Nichtterminal,  dem
  3800. sogenannten  replacement node. Das Muster legt fest, wo die Regel benutzt wer-
  3801. den kann. Nachdem dann die zugehoerige  Aktion  ausgefuehrt  wurde,  wird  der
  3802. Teilbaum durch den replacement node ersetzt.
  3803.  
  3804. Bei der Ausfuehrung von  Aktionen  werden  bei  Twig  verschiedene  Strategien
  3805. unterschieden.  Neben  dem  topdown-mode,  dessen Vorgehensweise der von ESTRA
  3806. entspricht, kennt Twig  noch  den  rewrite-mode  und  den  deferred-mode.  Der
  3807. deferred-mode  entspricht der Postfixstrategie und stellt somit lediglich eine
  3808. Abkuerzung dar, da die Transformation nicht explizit fuer die einzelnen Soehne
  3809. aufgerufen werden musz.
  3810.  
  3811. Diese Abkuerzung ist deshalb moeglich, weil Twig keine explizite  Auswahl  der
  3812. Funktionen  kennt,  mit  der  die einzelnen Blaetter des Musters zu bearbeiten
  3813. sind. Die Bearbeitung der Blaetter wird hier durch die Nichtterminale im  Mus-
  3814. ter  bestimmt.  Diese Nichtterminale muessen mit den replacement nodes der zur
  3815. Transformation der Blaetter angewandten Regeln uebereinstimmen. Eine mehrfache
  3816. Abbildung  eines  Teilbaums  mit  unterschiedlichen  Funktionen, wie ESTRA sie
  3817. zulaeszt, ist folglich mit Twig nicht moeglich.
  3818.  
  3819. Beim rewrite-mode, der von ESTRA nicht unterstuetzt wird,  wird  der  aktuelle
  3820. Teilbaum  durch  die  Aktion  ersetzt  und anschlieszend neu bearbeitet. Diese
  3821. Methode wird bei Twig angeboten, obwohl die Gefahr besteht, dasz es  zu  einem
  3822. endlosen Umschreiben kommt. Masznahmen zur automatischen Vermeidung eines sol-
  3823. chen endlosen Umschreibens werden von Twig nicht getroffen (vgl. Kapitel 5).
  3824.  
  3825. Der Zugriff auf den Baum erfolgt bei  Twig  ueber  einen  abstrakten  Datentyp
  3826. (ADT), wodurch eine weitgehende Unabhaengigkeit von der Darstellung des Baumes
  3827. erreicht wird.
  3828.  
  3829. In ESTRAL wurde auf die Verwendung eines ADTs hingegen verzichtet, um den Ver-
  3830. lust  an  Effizienz,  der  durch  die  in MODULA-2 notwendige Realisierung der
  3831. Operationen als Unterprogramme entsteht, zu vermeiden. Auf der  anderen  Seite
  3832. ist  dadurch  die  Flexibilitaet in der Darstellung der Baeume genommen.  Dies
  3833. ist jedoch nicht problematisch, da davon ausgegangen wird, dasz  der  Anwender
  3834. von  ESTRA  bei  der  Darstellung der Baeume das Werkzeug Ast [Gro89] zu Hilfe
  3835. nimmt. Denn das von Ast verwendete Format wurde bei der Entwicklung von  ESTRA
  3836. zugrundegelegt und wird somit voll unterstuetzt.
  3837.  
  3838. Zur Darstellung der zur Transformation noetigen Attribute wird bei  Twig  kein
  3839. Platz  in  den  Knoten des Baumes reserviert. Stattdessen wird eine neuer Baum
  3840. mit der selben Struktur aufgebaut, der diese Attribute sowie Verweise auf  die
  3841. Knoten des urspruenglichen Baumes aufnimmt.
  3842.  
  3843.  
  3844.  
  3845.  
  3846.  
  3847.  
  3848.  
  3849.  
  3850.  
  3851.  
  3852.  
  3853. 56                                        10. Vergleich mit anderen Werkzeugen
  3854.  
  3855.  
  3856. 10.2.  BEG
  3857.  
  3858. BEG (Back End Generator) [Emm88] ist ein Werkzeug zur automatischen  Erzeugung
  3859. effizienter  Codegeneratoren. Die Beschreibung erfolgt durch Baumersetzungsre-
  3860. geln.
  3861.  
  3862. Eine Baumersetzungsregel beschreibt die Reduktion  eines  Teilbaumes  auf  ein
  3863. Nichtterminal. Die Transformation des gesamten Baumes wird durch die Reduktion
  3864. des Baumes auf das Startsymbol bewirkt. Die Nichtterminale spielen  somit  die
  3865. selbe  Rolle  wie bereits bei Twig, sie stellen sicher, dasz die Regeln zusam-
  3866. menpassen.
  3867.  
  3868. Die einzelnen Regeln koennen hier ebenfalls mit Kosten  und  Bedingungen  ver-
  3869. sehen werden.
  3870.  
  3871. Dasz es sich bei BEG um ein spezielles Werkzeug zur Beschreibung von  Codegen-
  3872. eratoren   handelt,   zeigt  die  Tatsache,  dasz  BEG  spezielle  Mittel  zur
  3873. Beschreibung der Registervergabe zur Verfuegung stellt.
  3874.  
  3875. Auszerdem beschraenkt sich BEG auf die  fuer  die  Codeerzeugung  ausreichende
  3876. Postfixstrategie.  Dies  hat  den  Vorteil, dasz in den Regeln kein expliziter
  3877. Aufruf zur Transformation der Soehne erforderlich ist.  Andererseits  ist  BEG
  3878. damit fuer allgemeine Transformationen unbrauchbar.
  3879.  
  3880. 10.3.  OPTRAN
  3881.  
  3882. Die Spezifikationssprache OPTRAN [MWW84] wurde entwickelt, um die  Transforma-
  3883. tion  attributierter  Baeume  zu  beschreiben. Da hier verlangt wird, dasz das
  3884. Ergebnis der Transformation wieder ein attributierter Baum  ist,  koennen  die
  3885. Strukturen  der  Ein-  und Ausgabe durch attributierte Grammatiken beschrieben
  3886. werden.
  3887.  
  3888. Zur Beschreibung der Transformation werden Regeln benutzt, die  die  Abbildung
  3889. eines  Eingabe-Musters  in  ein  Ausgabe-Muster festlegen, wobei die Regeln so
  3890. geartet sein muessen, dasz sie entweder innerhalb einer  Struktur  (Ein-  oder
  3891. Ausgabe)  bleiben,  oder  den  Uebergang von der Eingabe- zur Ausgabe-Struktur
  3892. beschreiben.
  3893.  
  3894. Wie bereits in Kapitel 2 erwaehnt wurde, spielt die Reihenfolge,  in  der  die
  3895. Regeln  angewandt  werden,  bei  dieser  Methode  eine entscheidende Rolle. In
  3896. OPTRAN wird deshalb vom Benutzer verlangt, eine Strategie  zu  bestimmen,  die
  3897. diese festlegt.
  3898.  
  3899. Im Unterschied zu ESTRA legt OPTRAN besonderen Wert  auf  die  Attributierung.
  3900. Dabei wird zwischen einer Erstattributierung und einer Reattributierung unter-
  3901. schieden. Die Erstattributierung dient dazu, vor der Transformation die Attri-
  3902. bute  gemaesz der Eingabe-Grammatik zu berechnen. Nach der Transformation musz
  3903. der  Baum  gemaesz  der  Ausgabe-Grammatik  attributiert  sein.  Um  dies   zu
  3904. erreichen,  wird  nach  der  Anwendung  von  Regeln eine Reattributierung dur-
  3905. chgefuehrt,  die  sicherstellt,  dasz  Attribute,  die   sich   aufgrund   der
  3906. Regelanwendung geaendert haben, neu berechnet werden.
  3907.  
  3908.  
  3909.  
  3910.  
  3911.  
  3912.  
  3913.  
  3914.  
  3915.  
  3916.  
  3917.  
  3918.                                       57
  3919.  
  3920.  
  3921. 11.  Zusammenfassung
  3922.  
  3923. Mit ESTRAL wurde eine universelle Spezifikationssprache entwickelt, die geeig-
  3924. net ist, beliebige Transformationen attributierter Baeume zu beschreiben.
  3925.  
  3926. Durch die Verwendung von Mustern, Bedingungen und Kosten  koennen  Transforma-
  3927. tionen  auf natuerliche Weise, d.h. mehrdeutig beschrieben werden. Der sequen-
  3928. tiellen Natur der Transformation wird durch die  imperative  Beschreibung  der
  3929. einzelnen Vorschriften Rechnung getragen.
  3930.  
  3931. Um die Beschreibung einer Transformation automatisch in  eine  Implementierung
  3932. umzusetzen,  wurde  der  Generator ESTRA entwickelt.  Zur Umsetzung werden von
  3933. ESTRA zwei Versionen angeboten, die sich in  Bezug  auf  das  Pattern-Matching
  3934. unterscheiden.
  3935.  
  3936. Zum einen wird ein naives Pattern-Matching angeboten,  bei  dem  jedes  Muster
  3937. getrennt  betrachtet  wird,  zum  anderen  kann  auch  ein  Bottom-Up Pattern-
  3938. Matching, das alle Muster im Zusammenhang sieht, benutzt werden. Das Bottom-Up
  3939. Pattern-Matching  zahlt  sich insbesondere dann aus, wenn bei der Beschreibung
  3940. der Transformationen viele tiefe Muster verwendet werden.  Falls  es  hingegen
  3941. nur sehr einfache Muster gibt, ist das naive Pattern-Matching ueberlegen.
  3942.  
  3943. Erste eigene Einsaetze von ESTRA haben gezeigt, dasz die in ESTRAL  erstellten
  3944. Spezifikationen  in  Bezug  auf  die Wartbarkeit deutliche Vorteile gegenueber
  3945. einer  direkten  Implementierung  aufweisen.  Neben  dem   hoeheren   Abstrak-
  3946. tionsniveau  zahlt  sich vor allem die Moeglichkeit aus, Spezifikation zu ver-
  3947. bessern, in dem man Vorschriften hinzufuegt, um Spezialfaelle zu optimieren.
  3948.  
  3949. Zielsprache des Generators ist MODULA-2.   Erweiterungen  des  Generators  zur
  3950. Unterstuetzung   anderer  Programmiersprachen  (insbesondere  C)  wurden  aber
  3951. bereits beim Entwurf und der Implementierung des Generators vorbereitet.
  3952.  
  3953.  
  3954.  
  3955.  
  3956.  
  3957.  
  3958.  
  3959.  
  3960.  
  3961.  
  3962.  
  3963.  
  3964.  
  3965.  
  3966.  
  3967.  
  3968.  
  3969.  
  3970.  
  3971.  
  3972.  
  3973.  
  3974.  
  3975.  
  3976.  
  3977.  
  3978.  
  3979.  
  3980.  
  3981.  
  3982.  
  3983.                                       58
  3984.  
  3985.  
  3986. Anhang A: Syntax von ESTRAL
  3987.  
  3988. transformation                =TRANSFORMATION
  3989.             ident             Name der Transformation
  3990.             [ EXPORT '{' source_text '}' ]oeffentliche Vereinbarungen
  3991.             [ GLOBAL '{' source_text '}' ]globale Vereinbarungen
  3992.             [ BEGIN '{' source_text '}' ]Anweisungen zur Initialisierung
  3993.             [ CLOSE '{' source_text '}' ]Anweisungen zum Abschlusz
  3994.             grammar           Baumgrammatik
  3995.             function *        Funktionen
  3996. grammar = GRAMMAR
  3997.             ident             Name der Grammatik
  3998.             production *      Klassen
  3999. production                    =classKlasse
  4000.             node *            Knotenbeschreibungen
  4001. class   = [ ident '->' ]      Bezeichner der Oberklasse
  4002.             ident '='         Bezeichner der Klasse
  4003. node    = '|' (string | ident)Name des Knotens
  4004.             [ ':'ident ]      Bezeichner des Knotens
  4005.             '(' [ son || ',' ] ')'Soehne
  4006. son     = [ ident ':' ]       Name des Sohnes
  4007.           ident               Bezeichner der Klasse des Sohnes
  4008. function  =                   FUNCTION
  4009.             ident             Name der Funktion
  4010.             [attributes       vererbte Attribute
  4011.              '->'
  4012.              attributes]      synthetisierte Attribute
  4013.             [':' type]        Ergebnistyp
  4014.             domain            Definitionsbereich
  4015.             directive *       Vorschriften zur Beschreibung der Funktion
  4016. attributes                    =[ (ident || ','Liste von Bezeichnern
  4017.             ':' type)         Angabe des Typs
  4018.             || ';' ]          mehrere solche Listen durch ';' getrennt
  4019. type    = [ ident '.' ]       Angabe des Moduls zur Qualifikation
  4020.             ident             Bezeichner des Typs
  4021. domain  = '/' ident || ',' '/'Liste von Klassenbezeichnern
  4022. directive =                   patternMuster
  4023.             [ CONDITION '{' source_text '}' ]Bedingung
  4024.             [ COSTS (number | '{' source_text '}') ]Kosten
  4025.             [ DECLARE '{' source_text '}' ]lokale Vereinbarungen
  4026.             '{' source_text '}'Anweisungen zur Umsetzung
  4027. pattern = [ ident ] ':'        Selektor
  4028.             [ ident ]         Bezeichner der Klasse
  4029.         | ident               Selektor und Bezeichner der Klasse
  4030.         | [ [ ident ] ':' ]   Selektor
  4031.             (ident | string)  Name des Knotens
  4032.  
  4033.  
  4034.  
  4035.  
  4036.  
  4037.  
  4038.  
  4039.  
  4040.  
  4041.  
  4042. Anhang A: Syntax von ESTRAL                                                 59
  4043.  
  4044.  
  4045.             '(' [ pattern || ',' ] ')'Muster der Soehne
  4046.  
  4047.  
  4048.  
  4049.  
  4050.  
  4051.  
  4052.  
  4053.  
  4054.  
  4055.  
  4056.  
  4057.  
  4058.  
  4059.  
  4060.  
  4061.  
  4062.  
  4063.  
  4064.  
  4065.  
  4066.  
  4067.  
  4068.  
  4069.  
  4070.  
  4071.  
  4072.  
  4073.  
  4074.  
  4075.  
  4076.  
  4077.  
  4078.  
  4079.  
  4080.  
  4081.  
  4082.  
  4083.  
  4084.  
  4085.  
  4086.  
  4087.  
  4088.  
  4089.  
  4090.  
  4091.  
  4092.  
  4093.  
  4094.  
  4095.  
  4096.  
  4097.  
  4098.  
  4099.  
  4100.  
  4101.  
  4102.  
  4103.  
  4104.  
  4105.  
  4106.  
  4107.                                       60
  4108.  
  4109.  
  4110. Anhang B: Beispiel fuer die Anwendung von ESTRA
  4111.  
  4112. Anhang B1: Spezifikation in ESTRAL
  4113.  
  4114. TRANSFORMATION Trans
  4115. /*
  4116.  *   Quelltexterzeugung und Konstantenfaltung:
  4117.  *   - es wird MODULA-2 Quelltext ausgegeben
  4118.  *   - arithmetische und boolesche Konstanten werden gefaltet
  4119.  */
  4120. EXPORT    {
  4121. FROM Tree IMPORT    tTree;
  4122. }
  4123. GLOBAL    {
  4124. FROM StdIO     IMPORT    BeginIO, CloseIO, WriteS, WriteI, WriteNl, WriteIdent;
  4125. FROM Tree IMPORT    tTree;
  4126. }
  4127. BEGIN     {
  4128. BeginIO;
  4129. }
  4130. CLOSE     {
  4131. CloseIO;
  4132. }
  4133. GRAMMAR   Tree
  4134. /* statements */
  4135. stats     =
  4136. | Stats        (stat, stats)
  4137. | Stats0  ()
  4138. stat =
  4139. | If      (bExpr, then: stats, else: stats)
  4140. | ':=':   Assign    (index, aExpr)
  4141. /* arithmetic expressions */
  4142. aExpr     =
  4143. | '+':    Plus (lo: aExpr, ro: aExpr)
  4144. aExpr     ->
  4145. index     =
  4146. | aIdent  ()
  4147. aExpr     ->
  4148. aConst    =
  4149. | Const        ()
  4150. | '+'          (aConst, aConst)
  4151. /* boolean expressions */
  4152. bExpr     =
  4153.  
  4154.  
  4155.  
  4156.  
  4157.  
  4158.  
  4159.  
  4160.  
  4161.  
  4162.  
  4163. Anhang B1: Spezifikation in ESTRAL                                          61
  4164.  
  4165.  
  4166. | '<': Less    (lo: aExpr, ro: aExpr)
  4167. | bIdent  ()
  4168. bExpr     ->
  4169. bConst    =
  4170. | True         ()
  4171. | False        ()
  4172. | '<'          (aConst, aConst)
  4173. FUNCTION  Code           /stats, stat, aExpr, bExpr/
  4174. /*   Ausgabe von MODULA-2 Quelltext          */
  4175. /* statements */
  4176. Stats     (stat, stats)                 COSTS1
  4177. {    Code (stat);
  4178.      WriteS    (';'); WriteNl;
  4179.      Code (stats);            }
  4180. Stats0    ()                  COSTS     0
  4181. {}
  4182. If   (bConst, then: stats, else: stats)      CONDITION { BFold (bConst) = TRUE }
  4183.                                    COSTS     0
  4184. {    Code (then);             }
  4185. If   (bConst, then: stats, else: stats)      CONDITION { BFold (bConst) = FALSE }
  4186.                                    COSTS     0
  4187. {    Code (else);             }
  4188. If   (bExpr, then: stats, else: Stats0 ())   COSTS3
  4189. {    WriteS    ('IF ');
  4190.      Code (bExpr);
  4191.      WriteS    (' THEN'); WriteNl;
  4192.      Code (then);
  4193.      WriteS    (' END;');               }
  4194. If   (bExpr, then: Stats0 (), else: stats )  COSTS3
  4195. {    WriteS    ('IF NOT (');
  4196.      Code (bExpr);
  4197.      WriteS    (') THEN'); WriteNl;
  4198.      Code (else);
  4199.      WriteS    (' END;');               }
  4200. If   (bExpr, then: stats, else: stats)       COSTS4
  4201. {    WriteS    ('IF ');
  4202.      Code (bExpr);
  4203.      WriteS    (' THEN'); WriteNl;
  4204.      Code (then);
  4205.      WriteS    (' ELSE'); WriteNl;
  4206.  
  4207.  
  4208.  
  4209.  
  4210.  
  4211.  
  4212.  
  4213.  
  4214.  
  4215.  
  4216. 62                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4217.  
  4218.  
  4219.      Code (else);
  4220.      WriteS    (' END;');               }
  4221. ':=' (index, aExpr)           COSTS     1
  4222. {    Code (index);
  4223.      WriteS    (' := ');
  4224.      Code (aExpr);            }
  4225. /* arithmetic expressions */
  4226. '+'  (lo: aExpr, ro: aExpr)             COSTS1
  4227. {    WriteS    ('( ');
  4228.      Code (lo);
  4229.      WriteS    (' + ');
  4230.      Code (ro);
  4231.      WriteS    (' )');             }
  4232. aConst                        COSTS     1
  4233. {    WriteI    (AFold (aConst));        }
  4234. aIdent    ()                  COSTS     1
  4235. {    WriteIdent     (aIdent.ident);          }
  4236. '<'  (lo:aExpr, ro:aExpr)               COSTS1
  4237. {    WriteS    ('( ');
  4238.      Code (lo);
  4239.      WriteS    (' < ');
  4240.      Code (ro);
  4241.      WriteS    (')');              }
  4242. bIdent    ()                  COSTS     1
  4243. {    WriteIdent     (bIdent.ident);          }
  4244. bConst                        COSTS     1
  4245. {    IF BFold (bConst) THEN
  4246.        WriteS  ('TRUE');
  4247.      ELSE
  4248.        WriteS  ('FALSE');
  4249.      END;                }
  4250. FUNCTION  AFold      : INTEGER     /aConst/
  4251. /*   Faltung arithmetischer Konstanten       */
  4252. Const     ()                  COSTS     0
  4253. {    RETURN Const.value;           }
  4254. '+'  (lo:aConst, ro:aConst)             COSTS0
  4255. {    RETURN AFold (lo) + AFold (ro);    }
  4256.  
  4257.  
  4258.  
  4259.  
  4260.  
  4261.  
  4262.  
  4263.  
  4264.  
  4265.  
  4266. Anhang B1: Spezifikation in ESTRAL                                          63
  4267.  
  4268.  
  4269. FUNCTION  BFold      : BOOLEAN     /bConst/
  4270. /*   Faltung boolescher Konstanten      */
  4271. True ()                  COSTS     0
  4272. {    RETURN TRUE;             }
  4273. False     ()                  COSTS     0
  4274. {    RETURN FALSE;            }
  4275. '<'  (lo: aConst, ro: aConst)           COSTS0
  4276. {    RETURN AFold (lo) < AFold (ro);    }
  4277.  
  4278.  
  4279.  
  4280.  
  4281.  
  4282.  
  4283.  
  4284.  
  4285.  
  4286.  
  4287.  
  4288.  
  4289.  
  4290.  
  4291.  
  4292.  
  4293.  
  4294.  
  4295.  
  4296.  
  4297.  
  4298.  
  4299.  
  4300.  
  4301.  
  4302.  
  4303.  
  4304.  
  4305.  
  4306.  
  4307.  
  4308.  
  4309.  
  4310.  
  4311.  
  4312.  
  4313.  
  4314.  
  4315.  
  4316.  
  4317.  
  4318.  
  4319.  
  4320.  
  4321.  
  4322.  
  4323.  
  4324.  
  4325.  
  4326. 64                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4327.  
  4328.  
  4329. Anhang B2: Generierter Code
  4330.  
  4331. Im folgenden ist der von ESTRA generierte Code dargestellt.
  4332.  
  4333. Die Unterschiede, der beiden Versionen, die durch den optionalen  Einsatz  des
  4334. Bottom-Up  Pattern-Matching  entstehen,  werden so dargestellt, dasz der Leser
  4335. diese unmittelbar vergleichen kann.
  4336.  
  4337. (* ------ simple pattern-matching ------
  4338.    (A)
  4339.    --------------------------------------------- *)
  4340.    (B)
  4341. (* --- bottom-up pattern-matching --- *)
  4342. Beim Einsatz des Bottom-Up Pattern-Matching wird (B) generiert,
  4343. ansonsten wird (A) erzeugt.
  4344.  
  4345.  
  4346.  
  4347.  
  4348.  
  4349.  
  4350.  
  4351.  
  4352.  
  4353.  
  4354. DEFINITION MODULE Trans;
  4355. IMPORT Tree;
  4356.     (* line 3 Trans.estra *)
  4357. FROM Tree IMPORT    tTree;
  4358. (* ------ simple pattern-matching ------
  4359.    --------------------------------------------- *)
  4360. VAR TransTabName: ARRAY [0..127] OF CHAR;
  4361. (* --- bottom-up pattern-matching --- *)
  4362. PROCEDURE BeginTrans;
  4363. PROCEDURE DoTrans (yyt: Tree.tTree);
  4364. PROCEDURE CloseTrans;
  4365. END Trans.
  4366.  
  4367.  
  4368.  
  4369.  
  4370.  
  4371.  
  4372.  
  4373.  
  4374.  
  4375.  
  4376.  
  4377.  
  4378.  
  4379.  
  4380.  
  4381.  
  4382.  
  4383.  
  4384.  
  4385.  
  4386.  
  4387.  
  4388.  
  4389. Anhang B2: Generierter Code                                                 65
  4390.  
  4391.  
  4392. IMPLEMENTATION MODULE Trans;
  4393. (* ------ simple pattern-matching ------
  4394. IMPORT SYSTEM, IO, Memory, Tree;
  4395.    --------------------------------------------- *)
  4396. IMPORT SYSTEM, IO, Memory, SystemIO, Tree;
  4397. (* --- bottom-up pattern-matching --- *)
  4398.     (* line 7 Trans.estra *)
  4399. FROM StdIO     IMPORT    BeginIO, CloseIO, WriteS, WriteI, WriteNl, WriteIdent;
  4400. FROM Tree IMPORT    tTree;
  4401. CONST
  4402.   yyInfinite = 2147483643;
  4403.   yyBitsPerBitset = 32;
  4404. (* ------ simple pattern-matching ------
  4405.   yyCstats = 0;
  4406.   yyCstat = 1;
  4407.   yyCbExpr = 5;
  4408.   yyCindex = 3;
  4409.   yyCaExpr = 2;
  4410.   yyCaConst = 4;
  4411.   yyCbConst = 6;
  4412.   yyMaxClass = 6;
  4413.    --------------------------------------------- *)
  4414.   yySetSize = 22;
  4415.   yyMaxIndex = 26;
  4416.   yyCombSize = 117;
  4417.   yyStartState = 0;
  4418. (* --- bottom-up pattern-matching --- *)
  4419.   yyPoolSize = 10240;
  4420. TYPE
  4421.   yytBlockPtr = POINTER TO yytBlock;
  4422.   yytBlock =
  4423.   RECORD
  4424.     Successor: yytBlockPtr;
  4425.     Block: ARRAY [1..yyPoolSize] OF CHAR;
  4426.   END;
  4427. (* ------ simple pattern-matching ------
  4428.    --------------------------------------------- *)
  4429.   yyStateType = INTEGER;
  4430.   yySetType = ARRAY [0..yySetSize DIV yyBitsPerBitset] OF BITSET;
  4431.   yySetsType = ARRAY [0..yyMaxIndex] OF yySetType;
  4432.   yyCombType = ARRAY [0..yyCombSize] OF yyStateType;
  4433. (* --- bottom-up pattern-matching --- *)
  4434.   yyPCode = PROCEDURE (Tree.tTree);
  4435.   yyPAFold = PROCEDURE (Tree.tTree): INTEGER;
  4436.   yyPBFold = PROCEDURE (Tree.tTree): BOOLEAN;
  4437.   yyInfoPtr  = POINTER TO yyInfoType;
  4438.   yyInfoType =
  4439.  
  4440.  
  4441.  
  4442.  
  4443.  
  4444.  
  4445.  
  4446.  
  4447.  
  4448.  
  4449. 66                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4450.  
  4451.  
  4452.     RECORD
  4453. (* ------ simple pattern-matching ------
  4454.       yyClasses: ARRAY [0..yyMaxClass DIV yyBitsPerBitset] OF BITSET;
  4455.    --------------------------------------------- *)
  4456. (* --- bottom-up pattern-matching --- *)
  4457.       Code: RECORD Cost: INTEGER; Proc: yyPCode; END;
  4458.       AFold: RECORD Cost: INTEGER; Proc: yyPAFold; END;
  4459.       BFold: RECORD Cost: INTEGER; Proc: yyPBFold; END;
  4460.     END;
  4461. VAR
  4462.   yySets: yySetsType;
  4463.   yyComb: yyCombType;
  4464.   yyInfo: yyInfoType;
  4465.   yyMatch: ARRAY [0..22] OF BOOLEAN;
  4466.   yyBlockList: yytBlockPtr;
  4467.   yyPoolFreePtr, yyPoolEndPtr: SYSTEM.ADDRESS;
  4468. (* ------ simple pattern-matching ------
  4469. PROCEDURE yyClass (yyt: Tree.tTree;Bit, Set: INTEGER): BOOLEAN;
  4470. VAR info: yyInfoPtr;
  4471. BEGIN
  4472.   info := yyt^.yyEstraInfo;
  4473.   RETURN Bit IN info^.yyClasses [Set];
  4474. END yyClass;
  4475.    --------------------------------------------- *)
  4476. (* --- bottom-up pattern-matching --- *)
  4477. PROCEDURE yyAlloc (): SYSTEM.ADDRESS;
  4478. VAR BlockPtr: yytBlockPtr;
  4479. BEGIN
  4480.   IF LONGINT (yyPoolEndPtr - yyPoolFreePtr) < SYSTEM.TSIZE (yyInfoType) THEN
  4481.     BlockPtr  := yyBlockList;
  4482.     yyBlockList  := Memory.Alloc (SYSTEM.TSIZE (yytBlock));
  4483.     yyBlockList^.Successor := BlockPtr;
  4484.     yyPoolFreePtr := SYSTEM.ADR (yyBlockList^.Block);
  4485.     yyPoolEndPtr  := yyPoolFreePtr + yyPoolSize;
  4486.   END;
  4487.   INC (yyPoolFreePtr, SYSTEM.ADDRESS (SYSTEM.TSIZE (yyInfoType)));
  4488.   RETURN yyPoolFreePtr - SYSTEM.ADDRESS (SYSTEM.TSIZE (yyInfoType));
  4489. END yyAlloc;
  4490. PROCEDURE yyReleaseHeap;
  4491. VAR BlockPtr: yytBlockPtr;
  4492. BEGIN
  4493.   WHILE yyBlockList # NIL DO
  4494.     BlockPtr:= yyBlockList;
  4495.     yyBlockList:= yyBlockList^.Successor;
  4496.     Memory.Free (SYSTEM.TSIZE (yytBlock), BlockPtr);
  4497.   END;
  4498. END yyReleaseHeap;
  4499. PROCEDURE Code (yyt: Tree.tTree);
  4500. VAR InfoPtr: yyInfoPtr;
  4501. BEGIN
  4502.  
  4503.  
  4504.  
  4505.  
  4506.  
  4507.  
  4508.  
  4509.  
  4510.  
  4511.  
  4512. Anhang B2: Generierter Code                                                 67
  4513.  
  4514.  
  4515.   InfoPtr := yyInfoPtr (yyt^.yyEstraInfo);
  4516.   InfoPtr^.Code.Proc (yyt);
  4517. END Code;
  4518. PROCEDURE AFold (yyt: Tree.tTree): INTEGER;
  4519. VAR InfoPtr: yyInfoPtr;
  4520. BEGIN
  4521.   InfoPtr := yyInfoPtr (yyt^.yyEstraInfo);
  4522.   RETURN InfoPtr^.AFold.Proc (yyt);
  4523. END AFold;
  4524. PROCEDURE BFold (yyt: Tree.tTree): BOOLEAN;
  4525. VAR InfoPtr: yyInfoPtr;
  4526. BEGIN
  4527.   InfoPtr := yyInfoPtr (yyt^.yyEstraInfo);
  4528.   RETURN InfoPtr^.BFold.Proc (yyt);
  4529. END BFold;
  4530. PROCEDURE yyECode (yyt: Tree.tTree);
  4531. BEGIN
  4532.   IO.WriteS (IO.StdError, 'Function Code is not defined for this tree');
  4533.   IO.WriteNl (IO.StdError); IO.CloseIO; HALT;
  4534. END yyECode;
  4535. PROCEDURE yyEAFold (yyt: Tree.tTree): INTEGER;
  4536. BEGIN
  4537.   IO.WriteS (IO.StdError, 'Function AFold is not defined for this tree');
  4538.   IO.WriteNl (IO.StdError); IO.CloseIO; HALT;
  4539. END yyEAFold;
  4540. PROCEDURE yyEBFold (yyt: Tree.tTree): BOOLEAN;
  4541. BEGIN
  4542.   IO.WriteS (IO.StdError, 'Function BFold is not defined for this tree');
  4543.   IO.WriteNl (IO.StdError); IO.CloseIO; HALT;
  4544. END yyEBFold;
  4545. PROCEDURE yyF1Code (yyt: Tree.tTree);
  4546. BEGIN    (* line 72 Trans.estra *)
  4547.      Code (yyt^.Stats.stat);
  4548.      WriteS    (';'); WriteNl;
  4549.      Code (yyt^.Stats.stats);
  4550. END yyF1Code;
  4551. PROCEDURE yyF2Code (yyt: Tree.tTree);
  4552. BEGIN
  4553. END yyF2Code;
  4554. PROCEDURE yyF3Code (yyt: Tree.tTree);
  4555. BEGIN    (* line 90 Trans.estra *)
  4556.      Code (yyt^.If.then);
  4557. END yyF3Code;
  4558. PROCEDURE yyF4Code (yyt: Tree.tTree);
  4559. BEGIN    (* line 99 Trans.estra *)
  4560.      Code (yyt^.If.else);
  4561.  
  4562.  
  4563.  
  4564.  
  4565.  
  4566.  
  4567.  
  4568.  
  4569.  
  4570.  
  4571. 68                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4572.  
  4573.  
  4574. END yyF4Code;
  4575. PROCEDURE yyF5Code (yyt: Tree.tTree);
  4576. BEGIN
  4577. END yyF5Code;
  4578. PROCEDURE yyF6Code (yyt: Tree.tTree);
  4579. BEGIN    (* line 113 Trans.estra *)
  4580.      WriteS    ('IF ');
  4581.      Code (yyt^.If.bExpr);
  4582.      WriteS    (' THEN'); WriteNl;
  4583.      Code (yyt^.If.then);
  4584.      WriteS    (' END;');
  4585. END yyF6Code;
  4586. PROCEDURE yyF7Code (yyt: Tree.tTree);
  4587. BEGIN    (* line 124 Trans.estra *)
  4588.      WriteS    ('IF NOT (');
  4589.      Code (yyt^.If.bExpr);
  4590.      WriteS    (') THEN'); WriteNl;
  4591.      Code (yyt^.If.else);
  4592.      WriteS    (' END;');
  4593. END yyF7Code;
  4594. PROCEDURE yyF8Code (yyt: Tree.tTree);
  4595. BEGIN    (* line 135 Trans.estra *)
  4596.      WriteS    ('IF ');
  4597.      Code (yyt^.If.bExpr);
  4598.      WriteS    (' THEN'); WriteNl;
  4599.      Code (yyt^.If.then);
  4600.      WriteS    (' ELSE'); WriteNl;
  4601.      Code (yyt^.If.else);
  4602.      WriteS    (' END;');
  4603. END yyF8Code;
  4604. PROCEDURE yyF9Code (yyt: Tree.tTree);
  4605. BEGIN    (* line 148 Trans.estra *)
  4606.      Code (yyt^.Assign.index);
  4607.      WriteS    (' := ');
  4608.      Code (yyt^.Assign.aExpr);
  4609. END yyF9Code;
  4610. PROCEDURE yyF10Code (yyt: Tree.tTree);
  4611. BEGIN    (* line 157 Trans.estra *)
  4612.      WriteS    ('( ');
  4613.      Code (yyt^.Plus.lo);
  4614.      WriteS    (' + ');
  4615.      Code (yyt^.Plus.ro);
  4616.      WriteS    (' )');
  4617. END yyF10Code;
  4618. PROCEDURE yyF11Code (yyt: Tree.tTree);
  4619. BEGIN    (* line 168 Trans.estra *)
  4620.  
  4621.  
  4622.  
  4623.  
  4624.  
  4625.  
  4626.  
  4627.  
  4628.  
  4629.  
  4630. Anhang B2: Generierter Code                                                 69
  4631.  
  4632.  
  4633.      WriteI    (yyt^.Const.value);
  4634. END yyF11Code;
  4635. PROCEDURE yyF12Code (yyt: Tree.tTree);
  4636. BEGIN    (* line 175 Trans.estra *)
  4637.      WriteS    ('( ');
  4638.      Code (yyt^.Plus.lo);
  4639.      WriteS    (' + ');
  4640.      Code (yyt^.Plus.ro);
  4641.      WriteS    (' )');
  4642. END yyF12Code;
  4643. PROCEDURE yyF13Code (yyt: Tree.tTree);
  4644. BEGIN    (* line 186 Trans.estra *)
  4645.      WriteIdent     (yyt^.aIdent.ident);
  4646. END yyF13Code;
  4647. PROCEDURE yyF14Code (yyt: Tree.tTree);
  4648. BEGIN    (* line 193 Trans.estra *)
  4649.      WriteS    ('TRUE');
  4650. END yyF14Code;
  4651. PROCEDURE yyF15Code (yyt: Tree.tTree);
  4652. BEGIN    (* line 200 Trans.estra *)
  4653.      WriteS    ('FALSE');
  4654. END yyF15Code;
  4655. PROCEDURE yyF16Code (yyt: Tree.tTree);
  4656. BEGIN    (* line 207 Trans.estra *)
  4657.      WriteS    ('( ');
  4658.      Code (yyt^.Less.lo);
  4659.      WriteS    (' < ');
  4660.      Code (yyt^.Less.ro);
  4661.      WriteS    (')');
  4662. END yyF16Code;
  4663. PROCEDURE yyF17Code (yyt: Tree.tTree);
  4664. BEGIN    (* line 218 Trans.estra *)
  4665.      WriteIdent     (yyt^.bIdent.ident);
  4666. END yyF17Code;
  4667. PROCEDURE yyF18AFold (yyt: Tree.tTree): INTEGER;
  4668. BEGIN    (* line 229 Trans.estra *)
  4669.      RETURN yyt^.Const.value;
  4670. END yyF18AFold;
  4671. PROCEDURE yyF19AFold (yyt: Tree.tTree): INTEGER;
  4672. BEGIN    (* line 236 Trans.estra *)
  4673.      RETURN AFold (yyt^.Plus.lo) + AFold (yyt^.Plus.ro);
  4674. END yyF19AFold;
  4675. PROCEDURE yyF20BFold (yyt: Tree.tTree): BOOLEAN;
  4676. BEGIN    (* line 247 Trans.estra *)
  4677.  
  4678.  
  4679.  
  4680.  
  4681.  
  4682.  
  4683.  
  4684.  
  4685.  
  4686.  
  4687. 70                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4688.  
  4689.  
  4690.      RETURN TRUE;
  4691. END yyF20BFold;
  4692. PROCEDURE yyF21BFold (yyt: Tree.tTree): BOOLEAN;
  4693. BEGIN    (* line 254 Trans.estra *)
  4694.      RETURN FALSE;
  4695. END yyF21BFold;
  4696. PROCEDURE yyF22BFold (yyt: Tree.tTree): BOOLEAN;
  4697. BEGIN    (* line 261 Trans.estra *)
  4698.      RETURN AFold (yyt^.Less.lo) < AFold (yyt^.Less.ro);
  4699. END yyF22BFold;
  4700. PROCEDURE CostCode (yyt: Tree.tTree): INTEGER;
  4701. VAR
  4702.   InfoPtr: yyInfoPtr;
  4703. BEGIN
  4704.   InfoPtr := yyt^.yyEstraInfo;
  4705.   RETURN InfoPtr^.Code.Cost;
  4706. END CostCode;
  4707. PROCEDURE CostAFold (yyt: Tree.tTree): INTEGER;
  4708. VAR
  4709.   InfoPtr: yyInfoPtr;
  4710. BEGIN
  4711.   InfoPtr := yyt^.yyEstraInfo;
  4712.   RETURN InfoPtr^.AFold.Cost;
  4713. END CostAFold;
  4714. PROCEDURE CostBFold (yyt: Tree.tTree): INTEGER;
  4715. VAR
  4716.   InfoPtr: yyInfoPtr;
  4717. BEGIN
  4718.   InfoPtr := yyt^.yyEstraInfo;
  4719.   RETURN InfoPtr^.BFold.Cost;
  4720. END CostBFold;
  4721. (* ------ simple pattern-matching ------
  4722. PROCEDURE yyTraverse (yyt: Tree.tTree);
  4723.    --------------------------------------------- *)
  4724. PROCEDURE yyTraverse (yyt: Tree.tTree): yyStateType;
  4725. (* --- bottom-up pattern-matching --- *)
  4726. VAR
  4727.   state: yyStateType;
  4728.   match: POINTER TO yySetType;
  4729.   cost: INTEGER;
  4730.   info: yyInfoPtr;
  4731.   success: BOOLEAN;
  4732. BEGIN
  4733.   info := yyAlloc ();
  4734.   info^ := yyInfo;
  4735.   yyt^.yyEstraInfo := info;
  4736.   CASE yyt^.Kind OF
  4737.  
  4738.  
  4739.  
  4740.  
  4741.  
  4742.  
  4743.  
  4744.  
  4745.  
  4746.  
  4747. Anhang B2: Generierter Code                                                 71
  4748.  
  4749.  
  4750.   | Tree.Stats:
  4751. (* ------ simple pattern-matching ------
  4752.       yyTraverse (yyt^.Stats.stat);
  4753.       yyTraverse (yyt^.Stats.stats);
  4754.       INCL (info^.yyClasses [yyCstats DIV yyBitsPerBitset], yyCstats MOD yyBitsPerBitset);
  4755.    --------------------------------------------- *)
  4756.       state := 0;
  4757.       state := yyComb [state + yyTraverse (yyt^.Stats.stat)];
  4758.       state := yyComb [state + yyTraverse (yyt^.Stats.stats)];
  4759. (* --- bottom-up pattern-matching --- *)
  4760.       cost := 1
  4761.       + CostCode (yyt^.Stats.stat)
  4762.       + CostCode (yyt^.Stats.stats);
  4763.       IF cost < info^.Code.Cost THEN
  4764.         info^.Code.Cost := cost;
  4765.         info^.Code.Proc := yyF1Code;
  4766.       END;
  4767.   | Tree.Stats0:
  4768. (* ------ simple pattern-matching ------
  4769.       INCL (info^.yyClasses [yyCstats DIV yyBitsPerBitset], yyCstats MOD yyBitsPerBitset);
  4770.    --------------------------------------------- *)
  4771.       state := 1;
  4772. (* --- bottom-up pattern-matching --- *)
  4773.       cost := 0;
  4774.       IF cost < info^.Code.Cost THEN
  4775.         info^.Code.Cost := cost;
  4776.         info^.Code.Proc := yyF2Code;
  4777.       END;
  4778.   | Tree.If:
  4779. (* ------ simple pattern-matching ------
  4780.       yyTraverse (yyt^.If.bExpr);
  4781.       yyTraverse (yyt^.If.then);
  4782.       yyTraverse (yyt^.If.else);
  4783.       INCL (info^.yyClasses [yyCstat DIV yyBitsPerBitset], yyCstat MOD yyBitsPerBitset);
  4784.       yyMatch [3] := yyClass (yyt^.If.bExpr, yyCbConst MOD yyBitsPerBitset, yyCbConst DIV yyBitsPerBitset)
  4785.       & (          (* line 86 Trans.estra *)
  4786.      BFold (yyt^.If.bExpr) = TRUE  );
  4787.       yyMatch [4] := yyClass (yyt^.If.bExpr, yyCbConst MOD yyBitsPerBitset, yyCbConst DIV yyBitsPerBitset)
  4788.       & (          (* line 95 Trans.estra *)
  4789.      BFold (yyt^.If.bExpr) = FALSE      );
  4790.       yyMatch [5] := (yyt^.If.then^.Kind = Tree.Stats0)
  4791.        & (yyt^.If.else^.Kind = Tree.Stats0);
  4792.       yyMatch [6] := (yyt^.If.else^.Kind = Tree.Stats0);
  4793.       yyMatch [7] := (yyt^.If.then^.Kind = Tree.Stats0);
  4794.    --------------------------------------------- *)
  4795.       state := 1;
  4796.       state := yyComb [state + yyTraverse (yyt^.If.bExpr)];
  4797.       state := yyComb [state + yyTraverse (yyt^.If.then)];
  4798.       state := yyComb [state + yyTraverse (yyt^.If.else)];
  4799.  
  4800.  
  4801.  
  4802.  
  4803.  
  4804.  
  4805.  
  4806.  
  4807.  
  4808.  
  4809. 72                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4810.  
  4811.  
  4812.       match := SYSTEM.ADR (yySets [state]);
  4813.       yyMatch [3] := (3 IN match^[0]) & (          (* line 86 Trans.estra *)
  4814.      BFold (yyt^.If.bExpr) = TRUE  );
  4815.       yyMatch [4] := (4 IN match^[0]) & (          (* line 95 Trans.estra *)
  4816.      BFold (yyt^.If.bExpr) = FALSE      );
  4817.       yyMatch [5] := (5 IN match^[0]);
  4818.       yyMatch [6] := (6 IN match^[0]);
  4819.       yyMatch [7] := (7 IN match^[0]);
  4820. (* --- bottom-up pattern-matching --- *)
  4821.       IF yyMatch [3] THEN
  4822.         cost := 0
  4823.         + CostBFold (yyt^.If.bExpr)
  4824.         + CostCode (yyt^.If.then);
  4825.         IF cost < info^.Code.Cost THEN
  4826.           info^.Code.Cost := cost;
  4827.           info^.Code.Proc := yyF3Code;
  4828.         END;
  4829.       END;
  4830.       IF yyMatch [4] THEN
  4831.         cost := 0
  4832.         + CostBFold (yyt^.If.bExpr)
  4833.         + CostCode (yyt^.If.else);
  4834.         IF cost < info^.Code.Cost THEN
  4835.           info^.Code.Cost := cost;
  4836.           info^.Code.Proc := yyF4Code;
  4837.         END;
  4838.       END;
  4839.       IF yyMatch [5] THEN
  4840.         cost := 0;
  4841.         IF cost < info^.Code.Cost THEN
  4842.           info^.Code.Cost := cost;
  4843.           info^.Code.Proc := yyF5Code;
  4844.         END;
  4845.       END;
  4846.       IF yyMatch [6] THEN
  4847.         cost := 3
  4848.         + CostCode (yyt^.If.bExpr)
  4849.         + CostCode (yyt^.If.then);
  4850.         IF cost < info^.Code.Cost THEN
  4851.           info^.Code.Cost := cost;
  4852.           info^.Code.Proc := yyF6Code;
  4853.         END;
  4854.       END;
  4855.       IF yyMatch [7] THEN
  4856.         cost := 4
  4857.         + CostCode (yyt^.If.bExpr)
  4858.         + CostCode (yyt^.If.else);
  4859.         IF cost < info^.Code.Cost THEN
  4860.           info^.Code.Cost := cost;
  4861.           info^.Code.Proc := yyF7Code;
  4862.  
  4863.  
  4864.  
  4865.  
  4866.  
  4867.  
  4868.  
  4869.  
  4870.  
  4871.  
  4872. Anhang B2: Generierter Code                                                 73
  4873.  
  4874.  
  4875.         END;
  4876.       END;
  4877.       cost := 4
  4878.       + CostCode (yyt^.If.bExpr)
  4879.       + CostCode (yyt^.If.then)
  4880.       + CostCode (yyt^.If.else);
  4881.       IF cost < info^.Code.Cost THEN
  4882.         info^.Code.Cost := cost;
  4883.         info^.Code.Proc := yyF8Code;
  4884.       END;
  4885.   | Tree.Assign:
  4886. (* ------ simple pattern-matching ------
  4887.       yyTraverse (yyt^.Assign.index);
  4888.       yyTraverse (yyt^.Assign.aExpr);
  4889.       INCL (info^.yyClasses [yyCstat DIV yyBitsPerBitset], yyCstat MOD yyBitsPerBitset);
  4890.    --------------------------------------------- *)
  4891.       state := 19;
  4892.       state := yyComb [state + yyTraverse (yyt^.Assign.index)];
  4893.       state := yyComb [state + yyTraverse (yyt^.Assign.aExpr)];
  4894. (* --- bottom-up pattern-matching --- *)
  4895.       cost := 1
  4896.       + CostCode (yyt^.Assign.index)
  4897.       + CostCode (yyt^.Assign.aExpr);
  4898.       IF cost < info^.Code.Cost THEN
  4899.         info^.Code.Cost := cost;
  4900.         info^.Code.Proc := yyF9Code;
  4901.       END;
  4902.   | Tree.Plus:
  4903. (* ------ simple pattern-matching ------
  4904.       yyTraverse (yyt^.Plus.lo);
  4905.       yyTraverse (yyt^.Plus.ro);
  4906.       INCL (info^.yyClasses [yyCaExpr DIV yyBitsPerBitset], yyCaExpr MOD yyBitsPerBitset);
  4907.       IF yyClass (yyt^.Plus.lo, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset)
  4908.        & yyClass (yyt^.Plus.ro, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset) THEN
  4909.         INCL (info^.yyClasses [yyCaConst DIV yyBitsPerBitset], yyCaConst MOD yyBitsPerBitset);
  4910.       END;
  4911.       yyMatch [12] := yyClass (yyt^.Plus.lo, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset)
  4912.        & yyClass (yyt^.Plus.ro, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset);
  4913.       yyMatch [19] := yyClass (yyt^.Plus.lo, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset)
  4914.        & yyClass (yyt^.Plus.ro, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset);
  4915.    --------------------------------------------- *)
  4916.       state := 50;
  4917.       state := yyComb [state + yyTraverse (yyt^.Plus.lo)];
  4918.       state := yyComb [state + yyTraverse (yyt^.Plus.ro)];
  4919.       match := SYSTEM.ADR (yySets [state]);
  4920.       yyMatch [12] := (12 IN match^[0]);
  4921.       yyMatch [19] := (19 IN match^[0]);
  4922. (* --- bottom-up pattern-matching --- *)
  4923.       cost := 1
  4924.  
  4925.  
  4926.  
  4927.  
  4928.  
  4929.  
  4930.  
  4931.  
  4932.  
  4933.  
  4934. 74                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  4935.  
  4936.  
  4937.       + CostCode (yyt^.Plus.lo)
  4938.       + CostCode (yyt^.Plus.ro);
  4939.       IF cost < info^.Code.Cost THEN
  4940.         info^.Code.Cost := cost;
  4941.         info^.Code.Proc := yyF10Code;
  4942.       END;
  4943.       IF yyMatch [12] THEN
  4944.         cost := 1
  4945.         + CostCode (yyt^.Plus.lo)
  4946.         + CostCode (yyt^.Plus.ro);
  4947.         IF cost < info^.Code.Cost THEN
  4948.           info^.Code.Cost := cost;
  4949.           info^.Code.Proc := yyF12Code;
  4950.         END;
  4951.       END;
  4952.       IF yyMatch [19] THEN
  4953.         cost := 1
  4954.         + CostAFold (yyt^.Plus.lo)
  4955.         + CostAFold (yyt^.Plus.ro);
  4956.         IF cost < info^.AFold.Cost THEN
  4957.           info^.AFold.Cost := cost;
  4958.           info^.AFold.Proc := yyF19AFold;
  4959.         END;
  4960.       END;
  4961.   | Tree.aIdent:
  4962. (* ------ simple pattern-matching ------
  4963.       INCL (info^.yyClasses [yyCindex DIV yyBitsPerBitset], yyCindex MOD yyBitsPerBitset);
  4964.       INCL (info^.yyClasses [yyCaExpr DIV yyBitsPerBitset], yyCaExpr MOD yyBitsPerBitset);
  4965.    --------------------------------------------- *)
  4966.       state := 17;
  4967. (* --- bottom-up pattern-matching --- *)
  4968.       cost := 1;
  4969.       IF cost < info^.Code.Cost THEN
  4970.         info^.Code.Cost := cost;
  4971.         info^.Code.Proc := yyF13Code;
  4972.       END;
  4973.   | Tree.Const:
  4974. (* ------ simple pattern-matching ------
  4975.       INCL (info^.yyClasses [yyCaConst DIV yyBitsPerBitset], yyCaConst MOD yyBitsPerBitset);
  4976.       INCL (info^.yyClasses [yyCaExpr DIV yyBitsPerBitset], yyCaExpr MOD yyBitsPerBitset);
  4977.    --------------------------------------------- *)
  4978.       state := 16;
  4979. (* --- bottom-up pattern-matching --- *)
  4980.       cost := 1;
  4981.       IF cost < info^.Code.Cost THEN
  4982.         info^.Code.Cost := cost;
  4983.         info^.Code.Proc := yyF11Code;
  4984.       END;
  4985.  
  4986.  
  4987.  
  4988.  
  4989.  
  4990.  
  4991.  
  4992.  
  4993.  
  4994.  
  4995. Anhang B2: Generierter Code                                                 75
  4996.  
  4997.  
  4998.       cost := 1;
  4999.       IF cost < info^.AFold.Cost THEN
  5000.         info^.AFold.Cost := cost;
  5001.         info^.AFold.Proc := yyF18AFold;
  5002.       END;
  5003.   | Tree.Less:
  5004. (* ------ simple pattern-matching ------
  5005.       yyTraverse (yyt^.Less.lo);
  5006.       yyTraverse (yyt^.Less.ro);
  5007.       INCL (info^.yyClasses [yyCbExpr DIV yyBitsPerBitset], yyCbExpr MOD yyBitsPerBitset);
  5008.       IF yyClass (yyt^.Less.lo, yyCbConst MOD yyBitsPerBitset, yyCbConst DIV yyBitsPerBitset)
  5009.        & yyClass (yyt^.Less.ro, yyCbConst MOD yyBitsPerBitset, yyCbConst DIV yyBitsPerBitset) THEN
  5010.         INCL (info^.yyClasses [yyCbConst DIV yyBitsPerBitset], yyCbConst MOD yyBitsPerBitset);
  5011.       END;
  5012.       yyMatch [22] := yyClass (yyt^.Less.lo, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset)
  5013.        & yyClass (yyt^.Less.ro, yyCaConst MOD yyBitsPerBitset, yyCaConst DIV yyBitsPerBitset);
  5014.    --------------------------------------------- *)
  5015.       state := 73;
  5016.       state := yyComb [state + yyTraverse (yyt^.Less.lo)];
  5017.       state := yyComb [state + yyTraverse (yyt^.Less.ro)];
  5018.       match := SYSTEM.ADR (yySets [state]);
  5019.       yyMatch [22] := (22 IN match^[0]);
  5020. (* --- bottom-up pattern-matching --- *)
  5021.       cost := 1
  5022.       + CostCode (yyt^.Less.lo)
  5023.       + CostCode (yyt^.Less.ro);
  5024.       IF cost < info^.Code.Cost THEN
  5025.         info^.Code.Cost := cost;
  5026.         info^.Code.Proc := yyF16Code;
  5027.       END;
  5028.       IF yyMatch [22] THEN
  5029.         cost := 0
  5030.         + CostAFold (yyt^.Less.lo)
  5031.         + CostAFold (yyt^.Less.ro);
  5032.         IF cost < info^.BFold.Cost THEN
  5033.           info^.BFold.Cost := cost;
  5034.           info^.BFold.Proc := yyF22BFold;
  5035.         END;
  5036.       END;
  5037.   | Tree.bIdent:
  5038. (* ------ simple pattern-matching ------
  5039.       INCL (info^.yyClasses [yyCbExpr DIV yyBitsPerBitset], yyCbExpr MOD yyBitsPerBitset);
  5040.    --------------------------------------------- *)
  5041.       state := 23;
  5042. (* --- bottom-up pattern-matching --- *)
  5043.       cost := 1;
  5044.       IF cost < info^.Code.Cost THEN
  5045.         info^.Code.Cost := cost;
  5046.         info^.Code.Proc := yyF17Code;
  5047.  
  5048.  
  5049.  
  5050.  
  5051.  
  5052.  
  5053.  
  5054.  
  5055.  
  5056.  
  5057. 76                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  5058.  
  5059.  
  5060.       END;
  5061.   | Tree.True:
  5062. (* ------ simple pattern-matching ------
  5063.       INCL (info^.yyClasses [yyCbConst DIV yyBitsPerBitset], yyCbConst MOD yyBitsPerBitset);
  5064.       INCL (info^.yyClasses [yyCbExpr DIV yyBitsPerBitset], yyCbExpr MOD yyBitsPerBitset);
  5065.    --------------------------------------------- *)
  5066.       state := 18;
  5067. (* --- bottom-up pattern-matching --- *)
  5068.       cost := 1;
  5069.       IF cost < info^.Code.Cost THEN
  5070.         info^.Code.Cost := cost;
  5071.         info^.Code.Proc := yyF14Code;
  5072.       END;
  5073.       cost := 0;
  5074.       IF cost < info^.BFold.Cost THEN
  5075.         info^.BFold.Cost := cost;
  5076.         info^.BFold.Proc := yyF20BFold;
  5077.       END;
  5078.   | Tree.False:
  5079. (* ------ simple pattern-matching ------
  5080.       INCL (info^.yyClasses [yyCbConst DIV yyBitsPerBitset], yyCbConst MOD yyBitsPerBitset);
  5081.       INCL (info^.yyClasses [yyCbExpr DIV yyBitsPerBitset], yyCbExpr MOD yyBitsPerBitset);
  5082.    --------------------------------------------- *)
  5083.       state := 19;
  5084. (* --- bottom-up pattern-matching --- *)
  5085.       cost := 1;
  5086.       IF cost < info^.Code.Cost THEN
  5087.         info^.Code.Cost := cost;
  5088.         info^.Code.Proc := yyF15Code;
  5089.       END;
  5090.       cost := 0;
  5091.       IF cost < info^.BFold.Cost THEN
  5092.         info^.BFold.Cost := cost;
  5093.         info^.BFold.Proc := yyF21BFold;
  5094.       END;
  5095.   END;
  5096. (* ------ simple pattern-matching ------
  5097.    --------------------------------------------- *)
  5098.   RETURN state;
  5099. (* --- bottom-up pattern-matching --- *)
  5100. END yyTraverse;
  5101. (* ------ simple pattern-matching ------
  5102. PROCEDURE BeginTrans;
  5103. BEGIN
  5104.    --------------------------------------------- *)
  5105. PROCEDURE yyErrorCheck (i: INTEGER; s1, s2: ARRAY OF CHAR);
  5106. BEGIN
  5107.   IF i < 0 THEN
  5108.  
  5109.  
  5110.  
  5111.  
  5112.  
  5113.  
  5114.  
  5115.  
  5116.  
  5117.  
  5118. Anhang B2: Generierter Code                                                 77
  5119.  
  5120.  
  5121.     IO.WriteS (IO.StdError, s1);
  5122.     IO.WriteS (IO.StdError, s2);
  5123.     IO.WriteNl (IO.StdError); IO.CloseIO; HALT;
  5124.   END;
  5125. END yyErrorCheck;
  5126. PROCEDURE BeginTrans;
  5127. VAR yyf: SystemIO.tFile; yyi: INTEGER;
  5128. BEGIN
  5129.   yyf := SystemIO.OpenInput (TransTabName);
  5130.   yyErrorCheck (yyf, 'cannot open ', TransTabName);
  5131.   yyi := SystemIO.Read (yyf, SYSTEM.ADR (yySets), SYSTEM.TSIZE (yySetsType));
  5132.   yyErrorCheck (yyi, 'cannot read ', TransTabName);
  5133.   yyi := SystemIO.Read (yyf, SYSTEM.ADR (yyComb), SYSTEM.TSIZE (yyCombType));
  5134.   yyErrorCheck (yyi, 'cannot read ', TransTabName);
  5135.   SystemIO.Close (yyf);
  5136. (* --- bottom-up pattern-matching --- *)
  5137.     (* line 12 Trans.estra *)
  5138. BeginIO;
  5139. END BeginTrans;
  5140. PROCEDURE DoTrans (yyt: Tree.tTree);
  5141. VAR state: yyStateType;
  5142. BEGIN
  5143. (* ------ simple pattern-matching ------
  5144.   yyTraverse (yyt);
  5145.    --------------------------------------------- *)
  5146.   state := yyTraverse (yyt);
  5147. (* --- bottom-up pattern-matching --- *)
  5148.   Code (yyt);
  5149.   yyReleaseHeap;
  5150. END DoTrans;
  5151. PROCEDURE CloseTrans;
  5152. BEGIN
  5153.     (* line 16 Trans.estra *)
  5154. CloseIO;
  5155. END CloseTrans;
  5156. BEGIN
  5157.   TransTabName := 'Trans.tab';
  5158.   WITH yyInfo DO
  5159. (* ------ simple pattern-matching ------
  5160.     yyClasses [0] := {};
  5161.    --------------------------------------------- *)
  5162. (* --- bottom-up pattern-matching --- *)
  5163.     Code.Cost := yyInfinite;
  5164.     Code.Proc := yyECode;
  5165.     AFold.Cost := yyInfinite;
  5166.     AFold.Proc := yyEAFold;
  5167.     BFold.Cost := yyInfinite;
  5168.     BFold.Proc := yyEBFold;
  5169.   END;
  5170.  
  5171.  
  5172.  
  5173.  
  5174.  
  5175.  
  5176.  
  5177.  
  5178.  
  5179.  
  5180. 78                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  5181.  
  5182.  
  5183.   yyBlockList:= NIL;
  5184.   yyPoolFreePtr:= NIL;
  5185.   yyPoolEndPtr:= NIL;
  5186. END Trans.
  5187.  
  5188.  
  5189.  
  5190.  
  5191.  
  5192.  
  5193.  
  5194.  
  5195.  
  5196.  
  5197.  
  5198.  
  5199.  
  5200.  
  5201.  
  5202.  
  5203.  
  5204.  
  5205.  
  5206.  
  5207.  
  5208.  
  5209.  
  5210.  
  5211.  
  5212.  
  5213.  
  5214.  
  5215.  
  5216.  
  5217.  
  5218.  
  5219.  
  5220.  
  5221.  
  5222.  
  5223.  
  5224.  
  5225.  
  5226.  
  5227.  
  5228.  
  5229.  
  5230.  
  5231.  
  5232.  
  5233.  
  5234.  
  5235.  
  5236.  
  5237.  
  5238.  
  5239.  
  5240.  
  5241.  
  5242.  
  5243.  
  5244.  
  5245.                                       79
  5246.  
  5247.  
  5248. Anhang B3: Bottom-Up Pattern-Matching Automat
  5249.  
  5250. Relevante Muster:
  5251.  
  5252.  p<0> =   Stats (:, :)
  5253.  p<0> =   Stats (:, :)
  5254.  p<1> =   Stats0 ()
  5255.  p<2> =   If (bConst, :, :)
  5256.  p<3> =   If (:, :, Stats0 ())
  5257.  p<4> =   If (:, Stats0 (), :)
  5258.  p<5> =   If (:, :, :)
  5259.  p<6> =   ':=' (:, :)
  5260.  p<7> =   '+' (:, :)
  5261.  p<8> =   aConst
  5262.  p<9> =   index
  5263. p<10> =   '<' (:, :)
  5264. p<11> =   bIdent ()
  5265. p<12> =   bConst
  5266. p<13> =   Const ()
  5267. p<14> =   '+' (aConst, aConst)
  5268. p<15> =   True ()
  5269. p<16> =   False ()
  5270. p<17> =   '<' (aConst, aConst)
  5271. p<18> =   :
  5272.  
  5273.  
  5274.  
  5275.  
  5276.  
  5277.  
  5278.  
  5279.  
  5280.  
  5281.  
  5282.  
  5283.  
  5284.  
  5285.  
  5286.  
  5287.  
  5288.  
  5289.  
  5290.  
  5291.  
  5292.  
  5293.  
  5294.  
  5295.  
  5296.  
  5297.  
  5298.  
  5299.  
  5300.  
  5301.  
  5302.  
  5303.  
  5304.  
  5305.  
  5306.  
  5307.  
  5308.  
  5309.  
  5310. 80                             Anhang B: Beispiel fuer die Anwendung von ESTRA
  5311.  
  5312.  
  5313. Zustaende:
  5314.  
  5315.  q<0> =   { p<0>, p<18> }
  5316.  q<1> =   { p<1>, p<18> }
  5317.  q<2> =   { p<2>, p<3>, p<4>, p<5>, p<18> }
  5318.  q<3> =   { p<2>, p<3>, p<5>, p<18> }
  5319.  q<4> =   { p<2>, p<4>, p<5>, p<18> }
  5320.  q<5> =   { p<2>, p<5>, p<18> }
  5321.  q<6> =   { p<3>, p<4>, p<5>, p<18> }
  5322.  q<7> =   { p<3>, p<5>, p<18> }
  5323.  q<8> =   { p<4>, p<5>, p<18> }
  5324.  q<9> =   { p<5>, p<18> }
  5325. q<10> =   { p<6>, p<18> }
  5326. q<11> =   { p<7>, p<8>, p<14>, p<18> }
  5327. q<12> =   { p<7>, p<8>, p<18> }
  5328. q<13> =   { p<7>, p<18> }
  5329. q<14> =   { p<8>, p<13>, p<18> }
  5330. q<15> =   { p<8>, p<18> }
  5331. q<16> =   { p<9>, p<18> }
  5332. q<17> =   { p<10>, p<12>, p<17>, p<18> }
  5333. q<18> =   { p<10>, p<12>, p<18> }
  5334. q<19> =   { p<10>, p<18> }
  5335. q<20> =   { p<11>, p<18> }
  5336. q<21> =   { p<12>, p<15>, p<18> }
  5337. q<22> =   { p<12>, p<16>, p<18> }
  5338. q<23> =   { p<12>, p<18> }
  5339. q<24> =   { p<18> }
  5340.  
  5341.  
  5342.  
  5343.  
  5344.  
  5345.  
  5346.  
  5347.  
  5348.  
  5349.  
  5350.  
  5351.  
  5352.  
  5353.  
  5354.  
  5355.  
  5356.  
  5357.  
  5358.  
  5359.  
  5360.  
  5361.  
  5362.  
  5363.  
  5364.  
  5365.  
  5366.  
  5367.  
  5368.  
  5369.  
  5370.  
  5371.  
  5372.  
  5373.  
  5374.  
  5375. Anhang B3: Bottom-Up Pattern-Matching Automat                               81
  5376.  
  5377.  
  5378. Zustandsuebergangsfunktionen:
  5379.  
  5380. Stats    [q<2> - q<10>, q<24>]                 [q<0>, q<1>, q<24>]                            =   q<0>
  5381. Stats0                                                                                        =   q<1>
  5382. If       [q<17>, q<18>, q<21>, q<22>, q<23>]   [q<0>, q<24>]                  [q<0>, q<24>]   =   q<5>
  5383. If       [q<17>, q<18>, q<21>, q<22>, q<23>]   [q<0>, q<24>]                  [q<1>]          =   q<3>
  5384. If       [q<17>, q<18>, q<21>, q<22>, q<23>]   [q<1>]                         [q<0>, q<24>]   =   q<4>
  5385. If       [q<17>, q<18>, q<21>, q<22>, q<23>]   [q<1>]                         [q<1>]          =   q<2>
  5386. If       [q<19>, q<20>, q<24>]                 [q<0>, q<24>]                  [q<0>, q<24>]   =   q<9>
  5387. If       [q<19>, q<20>, q<24>]                 [q<0>, q<24>]                  [q<1>]          =   q<7>
  5388. If       [q<19>, q<20>, q<24>]                 [q<1>]                         [q<0>, q<24>]   =   q<8>
  5389. If       [q<19>, q<20>, q<24>]                 [q<1>]                         [q<1>]          =   q<6>
  5390. ':='     [q<16>, q<24>]                        [q<11> - q<16>, q<24>]                         =   q<10>
  5391. '+'      [q<11>, q<12>, q<14>, q<15>]          [q<11>, q<12>, q<14>, q<15>]                   =   q<11>
  5392. '+'      [q<11>, q<12>, q<14>, q<15>]          [q<13>, q<16>, q<24>]                          =   q<13>
  5393. '+'      [q<13>, q<16>, q<24>]                 [q<11> - q<16>, q<24>]                         =   q<13>
  5394. aIdent                                                                                        =   q<16>
  5395. Const                                                                                         =   q<14>
  5396. '<'      [q<11>, q<12>, q<14>, q<15>]          [q<11>, q<12>, q<14>, q<15>]                   =   q<17>
  5397. '<'      [q<11>, q<12>, q<14>, q<15>]          [q<13>, q<16>, q<24>]                          =   q<19>
  5398. '<'      [q<13>, q<16>, q<24>]                 [q<11> - q<16>, q<24>]                         =   q<19>
  5399. bIdent                                                                                        =   q<20>
  5400. True                                                                                          =   q<21>
  5401. False                                                                                         =   q<22>
  5402.  
  5403.  
  5404.  
  5405.  
  5406.  
  5407.  
  5408.  
  5409.  
  5410.  
  5411.  
  5412.  
  5413.  
  5414.  
  5415.  
  5416.  
  5417.  
  5418.  
  5419.  
  5420.  
  5421.  
  5422.  
  5423.  
  5424.  
  5425.  
  5426.  
  5427.  
  5428.  
  5429.  
  5430.  
  5431.  
  5432.  
  5433.  
  5434.  
  5435.                                       82
  5436.  
  5437.  
  5438. Literaturhinweise
  5439.  
  5440. [AGT87]   Alfred V. Aho, Mahadevan Ganapathi and Steven  W.  K.  Tjiang,  Code
  5441.           Generation  Using  Tree  Matching and Dynamic Programming, AT&T Bell
  5442.           Laboratories, 1987.
  5443.  
  5444. [BMW87]   Juergen  Boerstler,  Ulrich  Moencke  and  Reinhard  Wilhelm,  Table
  5445.           Compression  for  Tree  Automata,  Aachener  Informatik-Berichte 12,
  5446.           (1987), .
  5447.  
  5448. [Emm88]   Helmut     Emmelmann,     Automatische     Erzeugung     effizienter
  5449.           Codegeneratoren,   Diplomarbeit,   GMD   Forschungsstelle   an   der
  5450.           Universitaet Karlsruhe, Sep. 1988.
  5451.  
  5452. [Gro89]   Josef Grosch, Ast - A  generator  for  Abstract  Syntax  Trees,  GMD
  5453.           Forschungsstelle an der Universitaet Karlsruhe, Feb. 1989.
  5454.  
  5455. [HoO82]   Christoph M. Hoffmann and Michael J. O'Donnell, Pattern Matching  in
  5456.           Trees, J. ACM 29, 1 (Jan. 1982), 68-95.
  5457.  
  5458. [KeR83]   Brian W. Kernighan and Dennis M. Ritchie, Programmieren in C, Hanser
  5459.           Muenchen, 1983.
  5460.  
  5461. [Knu68]   D. E.  Knuth,  Semantics  of  Context-Free  Languages,  Mathematical
  5462.           Systems Theory 2, 2 (June 1968), 127-146.
  5463.  
  5464. [MWW84]   Ulrich Moenke, Beatrix  Weisgerber  and  Reinhard  Wilhelm,  How  to
  5465.           Implement   a  System  for  Manipulation  of  Attributed  Trees,  in
  5466.           Informatik Fachberichte, vol. 77, U. Ammann (ed.), Springer  Verlag,
  5467.           Mar. 1984.
  5468.  
  5469. [Wir85]   Niklaus Wirth, Programmieren in Modula-2, Springer Verlag, 1985.
  5470.  
  5471.  
  5472.  
  5473.  
  5474.  
  5475.  
  5476.  
  5477.  
  5478.  
  5479.  
  5480.  
  5481.  
  5482.  
  5483.  
  5484.  
  5485.  
  5486.  
  5487.  
  5488.  
  5489.  
  5490.  
  5491.  
  5492.  
  5493.  
  5494.  
  5495.  
  5496.  
  5497.  
  5498.  
  5499.  
  5500. Inhaltsverzeichnis                                                           2
  5501.  
  5502.  
  5503.    5.12.    Hauptbeschreibung ...........................................   28
  5504.    5.13.    Funktionen ..................................................   28
  5505.    5.14.    Typen .......................................................   28
  5506.    5.15.    Attribute ...................................................   29
  5507.    5.16.    Definitionbereich ...........................................   29
  5508.    5.17.    Vorschriften ................................................   30
  5509.    5.18.    Muster ......................................................   30
  5510.    5.19.    Anweisungen .................................................   31
  5511.    5.20.    Bedingungen .................................................   32
  5512.    5.21.    Kosten ......................................................   32
  5513.    5.22.    Vereinbarungen ..............................................   33
  5514.    5.23.    Integration .................................................   33
  5515.  
  5516. 6. Implementierung von Transformationen durch ESTRA .....................   35
  5517.    6.1.     Vorbereitung der Transformation .............................   35
  5518.    6.2.     Darstellung von Funktionen und Vorschriften .................   36
  5519.    6.3.     Darstellung der Attribute ...................................   37
  5520.    6.4.     Speicherverwaltung ..........................................   37
  5521.    6.5.     Berechnung der Klassen ......................................   37
  5522.    6.6.     Berechnung der zulaessigen Vorschriften .....................   38
  5523.    6.7.     Berechnung der kostenguenstigsten Vorschriften ..............   38
  5524.  
  5525. 7. Bottom-Up Pattern-Matching mit einem Baumautomaten ...................   40
  5526.    7.1.     Relevante Muster ............................................   40
  5527.    7.2.     Zustaende ...................................................   41
  5528.    7.3.     Zustandsuebergangsfunktionen ................................   42
  5529.    7.4.     Felder zur Darstellung der Zustandsuebergangsfunktionen .....   43
  5530.    7.5.     Automaten zur Darstellung der Uebergangsfunktionen ..........   44
  5531.    7.6.     Realisierung der Automaten ..................................   45
  5532.    7.7.     Vermeidung unnoetiger Zustaende .............................   47
  5533.    7.8.     Implementierung des Bottom-Up Pattern-Matching ..............   47
  5534.  
  5535. 8. Vollstaendigkeit .....................................................   49
  5536.    8.1.     Einhaltung des Definitionsbereichs ..........................   49
  5537.    8.2.     Ueberdeckung des Definitionsbereichs ........................   49
  5538.    8.3.     Terminierung ................................................   52
  5539.  
  5540. 9. Schnittstellen des Transformators ....................................   53
  5541.    9.1.     Struktur der Eingabebaeume ..................................   53
  5542.    9.2.     Schnittstelle des generierten Moduls ........................   54
  5543.  
  5544. 10.    Vergleich mit anderen Werkzeugen .................................   55
  5545.    10.1.    Twig ........................................................   55
  5546.    10.2.    BEG .........................................................   56
  5547.    10.3.    OPTRAN ......................................................   56
  5548.  
  5549. 11.    Zusammenfassung ..................................................   57
  5550.  
  5551. Anhang A: Syntax von ESTRAL .............................................   58
  5552.  
  5553. Anhang B: Beispiel fuer die Anwendung von ESTRA .........................   60
  5554.    Anhang B1: Spezifikation in ESTRAL ...................................   60
  5555.    Anhang B2: Generierter Code ..........................................   64
  5556.  
  5557.  
  5558.  
  5559.  
  5560.  
  5561.  
  5562.  
  5563.  
  5564.  
  5565.  
  5566. Inhaltsverzeichnis                                                           3
  5567.  
  5568.  
  5569.    Anhang B3: Bottom-Up Pattern-Matching Automat ........................   79
  5570.  
  5571. Literaturhinweise .......................................................   82
  5572.  
  5573.  
  5574.  
  5575.  
  5576.  
  5577.  
  5578.  
  5579.  
  5580.  
  5581.  
  5582.  
  5583.  
  5584.  
  5585.  
  5586.  
  5587.  
  5588.  
  5589.  
  5590.  
  5591.  
  5592.  
  5593.  
  5594.  
  5595.  
  5596.  
  5597.  
  5598.  
  5599.  
  5600.  
  5601.  
  5602.  
  5603.  
  5604.  
  5605.  
  5606.  
  5607.  
  5608.  
  5609.  
  5610.  
  5611.  
  5612.  
  5613.  
  5614.  
  5615.  
  5616.  
  5617.  
  5618.  
  5619.  
  5620.  
  5621.  
  5622.  
  5623.  
  5624.  
  5625.  
  5626.  
  5627.